Now / Writing

Hello, world (and all the other ones I didn't finish)

I’ve wanted a blog since 1999. I started writing code that year, and I needed a place to write about the stuff I was working on. The two have been roughly tied ever since.

I never maintained one properly.

The graveyard of prior attempts

A couple of NewsPro installs on free hosts, back when I was deep in Romhacking and CGI was the coolest thing on the web. Then Blogger, when “blog” became a verb. Posted once. Then WordPress. Then WordPress again. Then WordPress one more time, because clearly the issue was the theme.

Every round followed the same shape: buy a domain, fall down a six-hour rabbit hole comparing themes, write half of a hello-world post, get distracted, never come back. None of those were blog problems. They were me problems. Every time I sat down to write, I’d start architecting the system around the writing instead of doing the writing. Designing the system the writing lives in? That I could spend a weekend on.

What changed

I can pair with an AI agent now. I told it what I wanted: one folder of markdown, one command to deploy, no CMS, no framework, no JS on the client. It kept me from over-engineering it. Most of the thirty minutes it took to build this site were spent answering “do you want X or Y” questions, not waiting on code.

That’s the premise of this blog: post about the shit I never finished, but now I have AI.

The stack

Counted from the outside in:

  • Build script. A single build.mjs. Walks posts/, parses frontmatter with gray-matter, renders Markdown with markdown-it, highlights code at build time with @shikijs/markdown-it, writes pure HTML into dist/.
  • Templates. Plain JS tagged template literals. No JSX, no runtime, no hydration. It’s 2026 and somehow this is a controversial choice.
  • Styles. One styles.css. Dark, Inter everywhere, generous whitespace. I caved.
  • Dev server. A small Node HTTP server in dev.mjs with chokidar watching the source tree. Save, rebuild, reload.
  • Feeds. RSS, sitemap.xml, and robots.txt are generated by the same script. RSS, because I am old.
  • Hosting. GitHub Pages, custom domain via Cloudflare DNS-only (so Let’s Encrypt can issue certs against the origin).
  • CI/CD. One GitHub Actions workflow. Pushes to main that touch posts/** or site code build and deploy dist/ to Pages.
  • Analytics. GoatCounter. One <script> tag, only rendered in production. No cookies, no banner, no shame.
  • Config. None. There are no environment variables. Site title, domain, and author live as constants in site.config.mjs. If something changes, I open the file. It’s fine.

No CMS. No database. No complication.

What to expect here

Probably:

  1. Postmortems of shelved projects.
  2. Updates on the ones the agent and I are dragging across the finish line.
  3. Small notes on things that, against all odds, actually worked.

More soon. Or not. That’s kind of the point.