Created on February 28, 2023
Confession time... I kinda loathe front-end web development. Because of this, I have a huge soft spot for minimalist websites that convey information cleanly and concisely. Some famous examples include:
So, ideally, this website would be of a similar nature. I wanted something super lightweight that I could easily stand up and maintain without worrying about the underlying framework getting in the way. I ended up stumbling upon the eleventy (11ty) framework, and it fits this niche perfectly.
I love the simplicity of Markdown and wanted that to be the primary format - but Markdown alone isn't enough. 11ty allows you to use Markdown, Nunjucks, Handlebars, WebC, EJS, and raw HTML - all within the same template!
With the built-in functionality of multiple languages and frameworks, developers can structure their projects as they see fit and pull in data from various sources, e.g., JSON, YAML, or even external APIs. The hot-reload functionality allows you to quickly see changes in the browser without having to rebuild manually.
Here are a few 11ty plugins that I enabled:
I added a "cache buster" that generates a unique URL for static files. This functionality allows users to immediately see changes instead of waiting for the cache TTL to expire. During the build, it inserts a UNIX datetime as a query parameter to generate a unique URL for static files. This functionality is primarily used on the static CSS and JS files:
eleventyConfig.addFilter("bust", (url) => {
const [urlPart, paramPart] = url.split("?");
const params = new URLSearchParams(paramPart || "");
params.set("v", DateTime.local().toFormat("X"));
return `${urlPart}?${params}`;
});
Usage:
<link href="{{ '/css/styles.css' | url | bust }}" rel="stylesheet" />
Output:
<link href="/css/styles.css?v=1678309695" rel="stylesheet" />
prismjs is used for code formatting. It uses the autoloader functionality to dynamically load languages, removing the need to download all possible language parsers.
<head>
...
<script src="https://unpkg.com/prismjs@v1.x/components/prism-core.min.js"></script>
<script src="https://unpkg.com/prismjs@v1.x/plugins/autoloader/prism-autoloader.min.js"></script>
...
</head>
For the code formatting theme, I use a modified version of VS Code Dark+.
The infrastructure is quite simple and deployed from a single CloudFormation template.
┌────────────┐
│ │
│ ACM Cert │
│ │
└────────────┘
▲
│ ┌────────────────────────┐
│ │ │
┌───► http ────► │ S3 (redirect to https) │
┌────────────┐ ┌────────────┐ │ │ │
│ │ │ │ │ └────────────────────────┘
│ Route 53 │ ─────► │ CloudFront ├────┤
│ │ │ │ │ ┌────────────────────────┐
└────────────┘ └────────────┘ │ │ │
└───► https ───► │ S3 │
│ │
└────────────────────────┘
There is also a separate CloudFormation template for CodePipeline that automatically deploys updates.
Instead of external links to Google Fonts, I downloaded the fonts locally using this guide and the google-webfonts-helper tool.
Doing this reduces the number of API calls to external URLs and improves performance.
For posts that need an image gallery, I use the method described here along with the Photoswipe library.
With these tweaks, the site easily achieves a rating of 100/100 on all metrics in Google Pagespeed: