Design system

The colors, type, spacing, and components this site is built from. The page is generated from one tokens file.

Mostly type. Boxes, shadows, and color only show up when they have a job to do.

There is one accent color, green. It marks the timeline, link hovers, and focus.

Borders are 1px lines that separate things. Home, resume, blog, and this page all use the same layout: a sticky label on the left, a column to read on the right.

Components never hard-code a color, size, or space. Change a token in static/css/tokens.css and the whole site follows.

surface

bg#ffffff
bg-subtle#f7f8f9
bg-hover#f0f1f3
bg-inverse#0b0c0e

text

text-primary#0b0c0e
text-secondary#3b3f47
text-tertiary#6a6f78
text-inverse#ffffff

border

border#e8eaed
border-strong#d3d6db

accent

accent#2f7d5b
accent-hover#226246
accent-subtle#e9f4ee
focus#2f7d5b
--font-sansInter Variable, for body text and interface. The quick brown fox jumps over the lazy dog.
--font-displayNewsreader Variable, for headlines. The quick brown fox jumps over the lazy dog.
--font-monoui-monospace, for code. const site = build(content);
--text-displayEngineer turned PM
--text-h1Page and post titles
--text-h2Entry titles and section headings
--text-h3Role titles and subsections
--text-lgLede paragraphs and pull quotes
--text-bodyBody copy sits at seventeen pixels with generous leading so long posts stay easy to read.
--text-smNavigation, buttons, and supporting text
--text-xsDates, captions, and labels

Weights: regular 400 medium 510 semibold 590 display 500. Headings track tighter (-0.022em) as they get larger; body text uses the font default.

--space-1 · 0.25rem
--space-2 · 0.5rem
--space-3 · 0.75rem
--space-4 · 1rem
--space-5 · 1.5rem
--space-6 · 2rem
--space-7 · 3rem
--space-8 · 4rem
--space-9 · 6rem
--space-10 · 8rem

sm · 6px

md · 8px

lg · 12px

full · 999px

sm
md
TokenValue
--container70rem
--gutterclamp(1.25rem, 4vw, 2.5rem)
--column-meta11.5rem
--column-content40rem
--header-height3.5rem
--duration140ms
--easecubic-bezier(0.2, 0, 0, 1)
  • Product & AI
  • Climate
  • Data

Body copy with a link, strong text, and inline code.

Quotes get an accent rule and step up to the large size.

A neutral callout for asides.

An accent callout for the thing to remember.

.entry { display: grid; }
ToolWhat it does
TablesHairline rows, no vertical rules

The signature layout. A sticky label with an accent dot sits on the left of a continuous rule, and content sits in a 40rem column on the right. On narrow screens the rule is dropped and the label stacks above the content. The blog index uses a date as the label; the home and resume pages use section names.