How this site is built
Astro, MDX, four typefaces, and a name drawn in characters.
This site is a static Astro build. Pages are plain HTML, and the few scripts that exist are there for one job each: drawing the name at the top of the homepage, keeping the local clock current, and reporting what’s under the pointer on the contribution graph.
Writing in MDX
Posts are MDX files in src/content/writing. Each one needs a title, a description and a date in its frontmatter; everything else is Markdown, with components available when a post needs more than text.
---
title: How this site is built
description: Astro, MDX, four typefaces, and a name drawn in characters.
date: 2026-10-07
---
Setting draft: true keeps a post on the dev server and out of the production build.
The name in characters
The name on the homepage is set in Cal Sans and then rasterised into a grid of cells. Each cell measures how much of the letterform covers it and prints the character with roughly that much ink, from . for an edge to @ for a solid stroke:
const RAMP = [' ', '.', ':', '-', '=', '+', '*', '#', '%', '@'];
Because the characters come from coverage, the name stays legible at any width. The pointer adds ink to nearby cells, so the letters get heavier wherever the cursor is.
Type
| Typeface | Used for |
|---|---|
| Inter | Everything you read |
| Cal Sans | Names and headings |
| Geist Pixel Square | The character grid and large figures |
| Geist Pixel Line | Secondary figures on the contribution graph |
Inter runs with three OpenType features switched on: cv11 for the single-storey a, ss01 for open digits and ss02 for the disambiguated forms. Headings and the intro use -0.03em tracking; long paragraphs use a little less so they stay comfortable to read.
Contributions
The graph is built at deploy time from GitHub’s public contribution data, so the numbers are whatever they were on the day the site was last built.