Programming

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, and remark-gfm.
  • Pagefind for client-side search — indexes the built HTML after next build and 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

  1. The exact algorithm I use for "related posts" (it's not as simple as "same tag wins").
  2. A defense of data-pagefind-body as the cleanest way to scope a search index without fighting your CMS.
  3. Why I gave up on next/image for 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.