Hello, Programming
This section is for software notes — patterns I've found useful, tools that earn their place in my workflow, and the occasional post-mortem of a bug that taught me something. The first post is meta: a quick tour of how this blog itself is built, so I have a reference for the next time I forget.
The stack
The site is intentionally boring:
- Next.js in static-export mode (
output: "export") — every route is prerendered to plain HTML and CSS at build time. - Markdown for content, processed at build time with
gray-matter,remark, andremark-gfm. - Pagefind for client-side search — indexes the built HTML after
next buildand ships a small WASM bundle that loads only when someone starts typing. - Cloudflare Pages for hosting. No Workers, no Functions, no D1 — just
a CDN serving the
out/directory.
The build pipeline is essentially one line:
next build && pagefind --site out --output-subdir pagefind
That produces a fully static out/ directory that can be served from any
file host. No runtime, no surprises.
Why no Cloudflare Functions?
I considered putting search behind a Cloudflare Function — it's tempting when you're already on the platform — but for a blog this size it's worse on every axis I care about:
A Function adds a network round-trip to every keystroke, costs money once you stop being free, and pulls you out of the "fully static, deploy anywhere" mental model. Build-time indexing wins until you're well past ten thousand posts.
Pagefind generates a sharded index where each query only fetches the shards it needs. The first query downloads ~100 KB; subsequent queries are effectively free. Worth it.
Configurable sections
Adding a new section is just creating a folder under content/ with an
_index.md. The frontmatter looks like this:
title: Cooking
description: Recipes I keep coming back to.
order: 4
Posts are siblings of _index.md. There's no special compiler step and no
config file to edit — the file system is the config.
Post frontmatter
title: My post
date: 2026-05-07
tags: [foo, bar]
cover: https://example.com/cover.jpg # optional
If cover is missing, the build picks a stable picsum image seeded by the
post's path, so each post has a consistent placeholder until you upload
something real.
Things I want to write about next
- The exact algorithm I use for "related posts" (it's not as simple as "same tag wins").
- A defense of
data-pagefind-bodyas the cleanest way to scope a search index without fighting your CMS. - Why I gave up on
next/imagefor this project and went back to plain<img>tags.
Each of those probably deserves its own post, so I'll save them. For now, this is the floor — everything else builds on top of it.