Stack
Built with Astro, styled with Tailwind CSS v4, with a little Svelte for search and view counts. Hosted on Vercel. Comments run on Giscus, which stores them in GitHub Discussions. Page views live in Astro DB.
Typography
The default edition sets headings and buttons in Anton, a condensed display face that does the job a comic letterer's brush does. Interface text is Public Sans. The Route edition swaps those for Barlow Condensed and Barlow, which read like trail signage. Essays in both editions are set in Source Serif 4, chosen because it has an optical-size axis and holds up at 18px on a phone. Code is JetBrains Mono. Everything is served from this domain via Fontsource, so nothing is fetched from Google.
Editions
The site has two editions, switchable from the squares icon in the header. Panels is the default: a comic page. Ink on paper, Marvel red, caption yellow, one process cyan, and a night edition that flips ink and paper. Every index page is a grid of panels with caption boxes; pull quotes are speech bubbles. Route is a gravel ride: forest green, chalk, gravel orange and sage, with contour lines under everything. Both keep your light or dark preference, and the choice is remembered on this device.
Colour
Tokens are plain CSS custom properties with light-dark() values, one set per edition. The swatches below show whichever edition and theme you're looking at right now.
--backgroundpage--cardraised surface--mutedhover, pills--borderhairlines--foregroundink--muted-foregroundsecondary ink--linkslink text--accentaccent--highlightcaptions, selection--spotspot colour
Sound and haptics
Clicking anything on this site makes a small sound and, on phones that allow it, a small buzz. The sound is a 14 millisecond burst of filtered noise synthesised in the browser with Web Audio, so there are no audio files to download. I tried a packaged UI sound library first, but its shortest click was ten times longer and sounded like a notification. The buzz comes from web-haptics. It works on Android and on iOS before 26.5; Apple closed the loophole it relied on after that. The speaker icon in the header mutes both, and the choice is remembered.
Source
The whole thing is on GitHub.