Introduction

When I set out to make this site, I wanted something simple, lightweight, easy to maintain, and easy to back up. I didn't need a complicated CMS like Wordpress (and I sort of wanted to do everything myself anyway -- this portfolio itself is, at the end of the day, a portfolio project). However, a static site without a good framework is difficult to maintain. You have to edit a lot of files just to make quick changes. I wanted some sort of system that would allow me to have a static site, but to set up the templates and metadata once and just write content using markdown moving forward.

Some of the pros of this approach are:

  • No database to maintain.
  • Simple, static site that is easy to maintain, store, and back up. In order to lose my content, I need to lose both the S3 bucket it is hosted in, as well as the GitHub repo. If both of those things happen simultaneously, we probably have bigger issues going on.
  • Static content is less prone to failure.
  • The use of markdown, in theory, allows people who stumble onto my github to read the blog through the repo itself, with stylized mardown, if they really wanted to.

Some of the downsides of this approach are:

  • Lack of complexity. If you really want something complex with a lot of dynamic content, this just won't work for you.
  • If you don't set up your static site correctly, it can be a lot of work to maintain.
  • If you want to perform operations which would typically require a server, you're out of luck (but not quite! read on to learn how I used serverless architecture in this project.)

What is a Static Site Generator (SSG)?

So, what in the world is an SSG? Think of it as the minimalist's approach to web development. Instead of dealing with the heavy lifting of databases and server-side rendering, SSGs pre-build your entire website into static files—HTML, CSS, and JavaScript. These files are then served directly to your users.

Why should you care?:

  1. Speed: With no database queries or server-side processing slowing things down, your site loads at warp speed.

  2. Security: Static sites are a fortress against hackers. No server-side code means fewer vulnerabilities.

  3. Affordability: Hosting static sites is budget friendly. You can use platforms like GitHub Pages, Netlify, or Vercel to host your site for free (or next to nothing).

  4. Easy to Maintain: Forget about tedious updates and patches. With an SSG, managing your site is easier than ever. Just generate the static files and you're good to go.

  5. SEO Search engines love fast sites, and so do your visitors. A speedy, well-structured static site can boost your SEO .

In a nutshell, SSGs are the unsung heroes of the web development world. They offer a streamlined, efficient way to build and maintain websites without sacrificing performance or security. S

Enter Eleventy (11ty)!

Why eleventy?

To be honest, the initial choice of 'why Eleventy' was because I googled the best Static Site Generator and reddit told me that Eleventy was the way to go. I vetted other options in various reddit threads, and while there are certainly some very cool things happening with NextJS and Astro and Hugo, Eleventy just seemed more simple and straight forward for what I was trying to do. I'm glad I chose it. It was fun and easy to work with.

Here are seven reasons why I love Eleventy:

  1. Flexibility Without the Fuss: Eleventy doesn't lock you into a specific framework or language. Whether you're a fan of Markdown, Nunjucks, Liquid, Handlebars, or even plain HTML, Eleventy has got you covered. This flexibility means you can work in a way that feels natural to you, using the tools you're already comfortable with.

  2. Minimal Setup, Maximum Control: One of Eleventy's biggest strengths is its simplicity. You don't need to spend hours configuring things just to get started. Yet, despite its minimal setup, it offers powerful customization options. You get the control you need without the headache of a steep learning curve.

  3. Speed and Efficiency: Eleventy is fast. It builds your site quickly and efficiently, making it a great choice for projects of all sizes. Whether you're running a small personal blog or a large corporate site, Eleventy handles it with ease.

  4. Community and Ecosystem: Eleventy has a growing, vibrant community. This means plenty of plugins, templates, and resources to help you along the way. The community is active and supportive, so you're never alone in your Eleventy journey.

  5. Data Flexibility: Eleventy makes it easy to pull in data from various sources. Whether it's local markdown files, JSON, external APIs, or a headless CMS, Eleventy can handle it all. This makes it a powerful tool for creating dynamic, content-rich websites.

  6. Incremental Adoption: Already have a site and just want to try out Eleventy? No problem. You can incrementally adopt Eleventy in your existing project. This makes it a fantastic choice for developers who want to transition gradually without overhauling their entire setup.

  7. Great Documentation: Eleventy's documentation is thorough and beginner-friendly. It guides you through the process step-by-step, so you’re never left scratching your head. Whether you’re a newbie or a seasoned developer, you’ll find the resources you need to succeed.

What does an Eleventy Project look like?

Now that you’re sold on the idea of using Eleventy, let’s break down the structure and setup of an Eleventy project.

Project Structure

When you create an Eleventy project, you’ll typically see a directory structure like this:

my-eleventy-site/
├── src/
│   ├── _includes/
│   │   ├── layouts/
│   │   │   └── base.njk
│   ├── _data/
│   │   └── site.json
│   ├── posts/
│   │   ├── first-post.md
│   │   └── second-post.md
│   ├── index.md
│   └── about.md
├── .eleventy.js
└── _site/

Here’s a quick rundown of what each part does:

  • src/: This is where all your source files live. It's the main directory where you write your content and templates.

  • _includes/: This directory holds reusable parts of your site, such as layouts, partials, and other templates. For example, you might have a base layout that all your pages use.

  • _data/: This folder is where you store global data files. These can be JSON, JavaScript, or other formats. Data in this directory is available across your entire site.

  • posts/: A typical place to keep your blog posts or other content collections. You can organize content into directories to keep things tidy.

  • .eleventy.js: This is your Eleventy configuration file. It’s optional, but if you need to customize your build process or configure plugins, this is where you do it.

  • index.md and about.md: These are your content files. You can use Markdown, HTML, or any other templating language supported by Eleventy.

  • _site/: This is the output directory where Eleventy generates your static site. By default, it’s _site, but you can configure it to be dist or any other name in your .eleventy.js file.

My project

Now that you know a little bit about Eleventy, let's explore how I used it to create this site. I won't go into deep detail. I'll give you a basic overview and then highlight the areas that I found interesting.

Basic Structure

I like to think of the basic structure in two ways. The physical site itself and how it looks and the data model, which I like to think of as objects similar to something we'd see in an OOP language.

Physical Site Setup

The site has the following pages:

  • a home page.
  • a blog.
  • a projects page.
  • a resume page.
  • a contact page

There is a base template that all other pages inherit from, which in turn has a base css file that all other pages inherit. Each page has its own associated layout file and css file for further customization.

Data Model

In Eleventy, we can group data from markdown files into categories called collections. These collections can then be referecned in from the templates above to render your static content.

Here are the collections in my site, each followed by a sample markdown file.

  • posts: represents a blog post.
---
title: 'Hello, world!'
date: '2024-06-21'
tags: ['General']
image: '/assets/images/blog/1.webp'
rt: '10 min read'
description: Hello and welcome. Read this initial post for introductory information!
layout: 'layouts/post.html'
permalink: 'posts/project-spotlight-portfolio-site/index.html'
css: '/assets/css/post.css'
---

Content goes here
  • project: represens a project.
---
title: 'portfolio project'
image: '/assets/images/projects/portfolio.png'
technologies:
  [
    'HTML',
    'CSS',
    'JavaScript',
    'Eleventy',
    'Markdown',
    'Nunjucks',
    'AWS Lambda',
    'AWS API Gateway',
    'AWS SNS',
  ]
environment: 'Deployed to AWS S3 with CloudFront via GitHub Actions'
live_demo: 'https://example.com'
github_link: 'https://github.com/example/example'
layout: 'layouts/project.html'
permalink: 'projects/portfolio_project/index.html'
css: '/assets/css/project.css'
blog_post: '/'
---

Content Goes here
  • certification: represents an earned certification on the resume page.
---
title: 'Red Hat Certified System Administrator (RHCSA)'
logo: '/assets/images/certifications/rhcsa.png'
sortOrder: 2
---
  • job: represents a job on the resume page.
---
title: 'Acme Corp'
position: 'Senior Engineer'
dateRange: 'Sep 2023 – Present'
location: 'Remote'
logo: '/assets/images/companies/acmecorp.png'
sortOrder: 7
---

- job duty 1.
- job duty 2.
- job duty 3.
  • .eduction: represents an educational achievement.
---
school: 'University of Somewhere'
degree: 'Master of Science, Computer Science'
logo: '/assets/images/education/uos.png'
dateRange: 'Expected 2026'
sortOrder: 3
---

Project Hightlights

This whole project was really fun. If I had to narrow it down to the two facets I am most proud of, I would say the resume page and the contact page. Let's break those two down.

Resume page

The resume page is like a showcase of all the wonderful things that Eleventy can do. The entire page is modular and generated completly by the presence of .md files in an Eleventy collection. Adding, removing, or updating certifications, jobs, or education is as simple as adding, removing, or updating its corresponding md file. Once we set up the initial templates and styling, we don't have to touch them again.

One particularly interesting portion of this project is controlling how things show up on a page. For instance, jobs are listed in chronological order with the most recent first. Education is usually listed chronologically within a hierarchy. For certifications, you might want to change the order in which they appear to group similar certifications togther. This is easily done in Eleventy in two steps: specifying the sort order in the md file, and setting up the collection to be sorted by that sort order.

---
title: 'Red Hat Certified System Administrator (RHCSA)'
logo: '/assets/images/certifications/rhcsa.png'
sortOrder: 2
---

To make Eleventy utilize the sort order in the markdown, we need to add the following to our .eleventy.js config file:

config.addCollection('certifications', function (collectionApi) {
  return collectionApi
    .getFilteredByGlob('src/certifications/*.md')
    .sort((a, b) => {
      return a.data.sortOrder - b.data.sortOrder;
    });
});

This sorts the collection by the lowest sort order number to the highest. Now, when we iterate over this collection to use it in the layout, the order that we sort by is how they will appear on the resume page.

Contact Form

One of the most basic functionalities of a portfolio site is the ability to contact the owner, usually by filling out a contact form. However, we're using static content. We don't have a back end server to do things for us. How do we make this work?

Well, we could take the simple way. There're many services out there that will let you call an API and send an email. SendGrid comes immediately to mind. But what's the fun in that? If you use SendGrid's API, you're never really fully in charge of the features and functionality. You are at the mercy of the whim of SendGrid and product owners. When you experience a problem, you might be told it's "working as designed". When you need a feature that doesn't exist, you might be told it's "on the roadmap" (tech companies keep cartographers very busy.). Plus, we're here to learn. We're here to build. It's 2024. We have the cloud.

AWS to the Rescure

It's no secret I'm trying to grow and learn in AWS. As it happens, AWS has a group of offerings that will allow us to build our own, serverless api that will send our emails for us. I chose to use three AWS offerings to make this happen. AWS API Gateway, AWS Lambda, and AWS SNS.

AWS Services Explained

  • AWS API Gateway: This service allows developers to create, publish, maintain, monitor, and secure APIs at any scale. With API Gateway, you can create RESTful APIs and WebSocket APIs that enable real-time two-way communication.

  • AWS Lambda: Lambda is a compute service that lets you run code without provisioning or managing servers. You pay only for the compute time you consume. With Lambda, you can run code for virtually any type of application or backend service—all with zero administration.

  • AWS SNS (Simple Notification Service): SNS is a fully managed messaging service for both application-to-application (A2A) and application-to-person (A2P) communication. It enables you to decouple microservices, distributed systems, and serverless applications. SNS provides topics for high-throughput, push-based, many-to-many messaging. It can also be used to fan out messages to a large number of subscribers, including Lambda functions, HTTP endpoints, and email addresses.

The architecture for this is simple:

  1. Set up a new topic in SNS and add yourself as a subscriber with your email address.
  2. Set up a serverless API in AWS API Gateway with an endpoint that accepts a POST request with the required data from the contact form.
  3. The AWS Lambda function will be triggered by the API. It will publish a new message to the SNS topic.
  4. The message will be sent out to all subscribers.

I know this is high level. I plan to make a more in depth post about this soon.

Conclusion

Well, if you've made it this far, I applaud you. Thanks for sticking with me. I know it's verbose, but I really had a lot to say (honestly, I'd love to have discussed every aspect of the project, but you'd be reading for days!)