This website
My own site: about 190 static pages, no trackers. It serves as its own case study.
Context
A personal site where the content is supposed to connect: history events link to essays, essays link to projects, all on a shared data model.
The problem
Personal sites are usually disconnected pages: an about, some posts, no relationships. I wanted a graph. And since some of the readers sit behind restricted networks, the fonts are self-hosted too.
My role
Design, engineering and writing — one person, in the time that's left over.
Architecture
Content lives as typed TypeScript data, not a CMS — heavier to write, but type-checked and diffable in git. Fully static rendering. The timeline has two views: a spatial one for desktop, a semantic list for screen readers and small screens. No analytics served at all.
Trade-offs
TypeScript data files over a CMS cost writing speed and buy type safety and zero runtime dependencies — the right trade for a site that must survive neglect. Dual-rendering the timeline costs code and buys accessibility. Serving no analytics protects readers and costs me data I decided I don't need.
Execution
Next.js App Router with static prerendering, a command palette built over the same content modules the pages render, MDX essays compiled as React Server Components with no client-side MDX runtime, and a command palette over the same content graph.
Outcome
This site. A content model one person can extend by editing typed files — you're reading one of its pages.
What I learned
The content model is the architecture. Deciding what fields an 'event' has was harder and more useful than any page layout.