//← Back to Build Log

Hello World!

Why I am keeping a public build log, what goes in it, and how to generate blog posts with Eleventy.

Intro

Welcome to the first entry in the Build Log, my personal software engineering journal. It exists mainly to serve as my personal knowledge-repository of challenges faced, topics researched, discussions had, and decisions made in my day-to-day job building software. But if anyone else gets some value out of it, that's a great side-effect to have!

Why write a dev blog?

One of my favorite things about being a software engineer is the constant array of new challenges I get to research and solve for. Often, it's a pattern or concept I've seen before, but occasionally I get to tackle something that is brand new to me too. As the years go by, I find myself losing the finer details of what I learned and researched. I often remember the broad details of what I did, but lose the details of the whys and hows. In the process of documenting my work, I hope to lock in a deeper understanding of these challenges and solutions. And if not, the Build Log will serve as my personal decision audit-table where I can go in and see the specifics.

Putting my reasoning in public is also partly self-interested. The quickest way to find the flaw in your own thinking is to write it down and let someone correct you. So please feel free to reach out if you disagree with anything I write here, or have a better solution for a problem than what I came up with. I welcome any and all feedback I can get!

What goes in here

Expect more working notes and decision logging than hot takes and juicy gossip. Posts will mostly be short to medium length and almost always pulled from real work.

My current work is primarily in web application development, so expect topics like:

  • Multi-tenant data isolation patterns, especially when Postgres RLS is on the table.
  • Serverless trade-offs on AWS, mostly Go on Lambda with SST.
  • Auth flows you have to live with after you ship them.

If a post does not pass the "would I send this to a teammate" test, I will not publish it.

How it is built

The blog is Markdown plus Eleventy v3 on top of my otherwise hand-coded site. The rest of dustinvk.com is plain HTML/CSS/JS. To publish a post, I drop a .md file into posts/, push to main, and Cloudflare Pages rebuilds. No CMS, no component framework, no JavaScript at runtime beyond the existing theme switcher.

Why Eleventy

I wanted a static site generator with as little ceremony as possible. I'd been writing posts straight into HTML, which works exactly once. I didn't want a CMS either, since I'm the only one publishing here.

Eleventy was the simple middle ground: I write in Markdown, keep my own hand-coded design, and a new post is just a file I drop in and push. As a bonus, it's generic enough to reskin for any client sites I build.

Here are some more things I liked about Eleventy:

  • It ships zero client-side JavaScript by default. Whatever JS ends up in the build is JS I wrote or added on purpose.
  • It does not assume a frontend framework. Templates can be Nunjucks, Liquid, Markdown, or plain HTML, and they mix freely.
  • The config is one JavaScript file. No magic, no plugin ecosystem you have to learn before you can ship.
  • It only processes the file types I opt into and copies everything else across with passthrough copy, so my existing hand-coded pages ship exactly as I wrote them.

Eleventy is the simplest tool that gets the job done.

A short setup tour

If you want to do the same, the four moving parts are: a config file, a folder of Markdown posts, a layout that wraps each post, and a build command. The whole thing fits on one screen.

1. Install it.

npm init -y
npm install --save-dev @11ty/eleventy

2. Write a minimal eleventy.config.js. This tells Eleventy where to read from, where to write to, and which file types to treat as templates.

export default function (eleventyConfig) {
  return {
    dir: { input: ".", output: "_site", includes: "_includes" },
    templateFormats: ["njk", "md"],
    markdownTemplateEngine: "njk",
  };
}

Set "type": "module" in your package.json if you want the ESM syntax above. Anything that is not one of those template formats (CSS, images, my existing hand-coded HTML) stays out of the template pipeline. I copy those across with eleventyConfig.addPassthroughCopy(...), which is how the rest of the site comes through the build untouched.

3. Make a layout at _includes/layouts/post.njk. It wraps every post. Nunjucks is just HTML with {{ variables }} and {% blocks %}:

<!doctype html>
<html lang="en">
<head><title>{{ title }}</title></head>
<body>
  <h1>{{ title }}</h1>
  <article>{{ content | safe }}</article>
</body>
</html>

4. Write a post at posts/hello.md. The frontmatter tells Eleventy which layout to use and provides the variables that layout reads.

---
title: Hello
layout: layouts/post.njk
---

Hi, this is my first post.

5. Build and preview.

npx @11ty/eleventy           # one-shot build to _site/
npx @11ty/eleventy --serve   # local dev server at http://localhost:8080

That is the entire happy path. The Eleventy docs are genuinely good. The Get Started page covers everything above in more depth, and Collections is where things start to get interesting.

Where it goes from here

The next thing you probably want is a collection to power a post list. Here is a trimmed version of the one driving this page. It grabs every Markdown file under posts/, drops anything marked draft: true, and sorts newest first:

eleventyConfig.addCollection("posts", (api) =>
  api
    .getFilteredByGlob("posts/*.md")
    .filter((p) => !p.data.draft)
    .sort((a, b) => b.date - a.date)
);

After that, the usual additions are an RSS feed via @11ty/eleventy-plugin-rss and code syntax highlighting via @11ty/eleventy-plugin-syntaxhighlight. Both are one-line additions in your config.

I also plan on using giscus to power a comment system in my blog posts via Github Discussions. But I will save that for another day.

Configuring Eleventy on Cloudflare Pages

Wiring this up to Cloudflare Pages took about 30 seconds. In the build configuration you pick Eleventy as the framework preset, which fills in the build command (npx @11ty/eleventy) and the output directory (_site) for you. The only thing I added by hand was a NODE_VERSION environment variable set to 20, so the build runs on a current Node. That is the whole setup, and every push to main rebuilds and deploys on its own. Almost too easy.

Final notes

There you have it. My thoughts on developer blogging, choosing the right tool, and a very quick rundown of how to setup Eleventy to power your own personal blog through basic .MD files.

Next up, I'll be diving into a practical security migration: How to seamlessly upgrade user password hashing algorithms in a Spring Boot web app without disrupting the user experience. I'll cover how to audit the existing setup, implement a rolling migration strategy that upgrades hashes dynamically upon user login, and handle the database schema updates without downtime.

That's all for today. Let's build! 🚀

Party mode enabled!