Design system
The actual tokens and primitives this site renders with, imported from the same code the pages use, so this page cannot drift from reality. Quiet, typography-led, near-monochrome with one accent.
Principles
- Typography does the design: hierarchy from size, weight, and space, not boxes.
- One accent colour, spent sparingly on links and selection.
- Hairline borders separate; backgrounds stay out of the way.
- Every element earns its place. If it doesn't inform, it goes.
- Server-rendered and semantic first; scripts only enhance.
Colour
Tokens are OKLCH with a 140° green hue thread. Toggle the theme to see both modes:
--bgbgPage background--surfacesurfaceCode blocks, subtle panels--inkinkBody text, primary buttons--mutedmutedSecondary text, quiet links--accentaccentLinks, selection, the one colour--borderborderHairlines, dividers--border-strongborder-strongInteractive borders
Type
Newsreader (serif) for display, Geist for body and UI, Geist Mono for code and data. Body measure caps at 65ch via max-w-prose.
Layout
One column. The page shell (header, stats bar, main, footer) is max-w-5xl so desktop space is used; the CV alone stays max-w-3xl for a document-like measure. Prose always caps at max-w-prose regardless of shell width. Dated entries use the two-column entry-grid pattern with an 8.5rem date gutter, stacking on mobile.
Spacing rhythm
gap-x-4 / 1remBetween inline linksmt-3 / 0.75remHeading to its subtitlemt-6 / 1.5remHeading to section contentspace-y-10 / 2.5remBetween entries in a listmt-16 / 4remBetween page sectionspy-16 / 4remPage top and bottom padding
Primitives
TextLink · accent / quiet / ink
Button · primary / secondary / ghost
SegmentedControl · version toggle (links, aria-current)
BlogToc · post table of contents (h2/h3, nested)
TextInput · Select · Checkbox
EntryGrid · dated entries (CV, education, lists)
Entry heading
Organisation · context note
Body content sits in the right column; the left gutter carries the date in tabular figures.
MetaText · DateStamp
Secondary information
Divided list (repo table rows)
- first itemTypeScript · Jul 2026
- second itemTypeScript · Jul 2026
Prose (blog posts)
Long-form content uses prose-quiet: comfortable line height, accent links, and surface-tinted code blocks.
pnpm buildSelection
Select this sentence to see the accent selection colour.
Iconography
Brand icons use official simple-icons paths; the mail icon is custom to match the hairline style. All render at 16px (12px inline), take currentColor, and are aria-hidden with an accessible label on the surrounding link.
MailIconGitHubIconGitLabIconLinkedInIconXIconOpenAIIconClaudeIconRssIcon
Focus
Keyboard focus gets a 2px accent ring with 2px offset via a global :focus-visiblerule; pointer clicks don't. The palette input is the exception: it fills its dialog edge-to-edge, so instead of a ring its bottom hairline turns accent on focus. Tab to the button to see the ring:
Motion
Motion is limited to colour and opacity transitions on hover — no movement, no entrances. Everything is disabled under prefers-reduced-motion.