Skip to content

Type

Three registers and a signature: what you operate, what you scan, what you read at size, and the name. Every family is self-hosted. Each stack names a licensed face first and ships a free one behind it, so a bought cut can be dropped in without touching a component.

Interface

Geist

Nav, controls, pills, the capability row. A product face: geometric and uniform, which is exactly right on a label and tiring across a paragraph, so it sets none of the prose.

'Söhne', 'Geist Variable', 'Helvetica Neue', Arial, ui-sans-serif, system-ui, sans-serif

Instrument

Geist Mono

Eyebrows, metadata rows, micro-labels, code. The companion cut to the interface face, so the label tier and the UI tier share a drawing rather than being two unrelated designs asked to sit a line apart.

'Berkeley Mono', 'Geist Mono Variable', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace

Reading

Source Serif 4

Long-form prose, essay headings, and since 2026-08 the display face too. It ships a real italic, which is why it replaced Literata: that one was CDN-hosted without one, so every emphasis in an essay was a synthesised slant.

'Tiempos Text', 'Source Serif 4 Variable', ui-serif, Charter, Georgia, serif

Wordmark

Joshua Udensi

The name, and nothing else. It dressed essay headings and blockquotes until 2026-08, which contradicted its own rule; those moved to the reading face.

'Fraunces Variable', 'Fraunces', ui-serif, 'Iowan Old Style', Georgia, serif

Ground

Two grounds, both first-class. Dark is the default and the brand register; the stone paper is a full theme rather than a reading mode. Neither is pure black or pure white: black is a floor the display cannot go below, so it gives the eye nothing to place a raised surface against.

Ground
Ink#090a09 Paper#eae9e3
Raised surface
Ink#0d0f0e Paper#e5e4dd
Display text
Ink#f2efe7 Paper#1c211f
Long-form prose
Ink#d2cec5 Paper#343a36
Supporting
Ink#aaa69e Paper#485a5e
Structure
Ink#718a98 Paper#26596b
Signal
Ink#b88a32 Paper#7a6410

The site once set warm cream text on a cool blue-grey ground, a separation of about 176 degrees and very nearly complementary. The eye's lens refracts short wavelengths more than long ones, so blue comes to focus slightly in front of the retina and amber slightly behind, and across a page the eye cannot hold both at once. That is felt as softness and strain, and no typeface fixes it. Both grounds are near-hueless now.

Measure

Reading column

38rem

Measured at 68.1 characters per line at 19px in the reading face, which sits on the ceiling of the 65 to 68 band rather than near its middle. It never widens with the viewport: a longer line wants a different size or a different face, not a wider column.

Margin rail

12rem

A second track for marginalia, never a subtraction from the reading column. Below 1100px it folds underneath, because nothing load-bearing lives there alone.

Press

Framework

SvelteKit, Svelte 5 with runes

Styling

Tailwind v4, tokens in layout.css

Long-form

mdsvex, with hand-rolled rehype passes

Hosting

Vercel, prerendered

Measurement

Umami Cloud and Vercel Speed Insights

No third-party fonts, stylesheets or images: the faces are self-hosted and the icons are generated from one source mark. One third-party script loads at runtime, Umami Cloud, which is configured cookieless. Vercel Speed Insights is served from this origin. The events this site sends are enumerated in a single schema that rejects free text, full URLs and anything it does not recognise.

Both grounds clear AA per token rather than per page, and every animation is gated on prefers-reduced-motion.