How this is made
A record of what this site runs on and why it looks the way it does. Mostly for my own memory, but you're welcome to it.
This site is built by hand (with a few exceptions) and kept deliberately small. There are no ads, pop-ups, or cookie banner (there's nothing to ask your consent for). Pages are rendered to static HTML at build time and served as files.
The design leans on rules and typography rather than boxes and shadows. Posts sit in an index rather than a grid of cards, metadata hangs in the margin where print would put it, and the accent colour is used sparingly enough that it still means something when it turns up.
"With a few exceptions" in the first paragraph means that I used AI to help me generate a few UI elements that would otherwise be pretty difficult to build, like the fancy hero background effect, but otherwise I built and designed everything by hand.
Stack
- Astro output: 'static'. Every route is prerendered to HTML at build time and served as flat files. No islands, no hydration, no framework runtime on the client.
- Sanity Headless CMS. Content is pulled with GROQ queries at build time and Portable Text is rendered to HTML through Astro components.
- Tailwind CSS v4 + SCSS Design tokens are CSS custom properties on :root, overridden under .dark and mapped into Tailwind with @theme. An inline script sets the theme class before first paint, so there is no flash of the wrong theme.
- Vanilla TypeScript The theme toggle, share button, reading progress bar and hero canvas are plain <script> modules inside Astro components, bundled by Vite.
- Shiki Highlighted at build time into inline-styled HTML. No highlighter or grammar files are sent to the browser.
- KaTeX renderToString at build time. The browser gets HTML and a stylesheet, not the KaTeX library.
- Sharp Astro's image service resizes and re-encodes images from the Sanity CDN during the build.
- @playform/compress Minifies the HTML, CSS, JS and SVG output after the build.
- Google Search Console SEO analytics only, no tracking scripts are loaded on the site, and no personal data is ever sent to Google. I use the Search Console to see which pages are indexed and how they perform in search results.
Type
- Newsreader A serif with an optical size axis, so it adjusts its details for small and large text.
- Archivo A plain sans for the interface around the writing.
- Fira Code Monospace for code blocks and inline code.
Source
Fonts are self-hosted, so nothing is requested from a font CDN when you load a page. If you want to see how any of this is put together, the code is on GitHub.