How this blog is built
A few people asked what’s under this site, so here’s the whole stack. The goals were simple: free hosting, custom domain, zero servers, Markdown in / Markdown out, and code blocks that don’t look like 2012.
The stack
- Astro — the static site generator. Posts are Markdown (or MDX when I need a React-less component). Astro 7’s content layer with a zod schema means a typo’d date fails the build instead of silently breaking the site.
- Astro’s built-in Shiki — for the code blocks. Same highlighting engine as
VS Code, with a light/dark dual theme that swaps with the site toggle:
import { glob } from 'astro/loaders'; const blog = defineCollection({ loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }), }); - Cloudflare Workers Static Assets — the host. A pure static site needs no Worker
script and no SSR adapter; the entire
wrangler.jsoncis four lines:{ "name": "personal-blog", "compatibility_date": "2026-07-25", "assets": { "directory": "./dist/" } } - GitHub Actions with
cloudflare/wrangler-action@v4— every push tomainbuilds and deploys. Cloudflare serves unlimited static requests on the free tier, so a popular post costs me $0 in bandwidth.
Why this over, say, Ghost or Medium
Because it’s plain text in a git repo. I edit a Markdown file, push, and a minute later it’s live. No database, no CMS login page, no renewing a $200/yr newsletter tool. readers get an RSS feed; I get my words back whenever I want.
There’s a longer note on the drafting workflow — editor, images, diagrams — coming next. For now, this is the “show your work” version of the site itself.