Skip to main content
ADR-009accepted

Geist Font Family as Design System Foundation

Context

Typography selection for a portfolio site is a high-leverage decision that affects perceived quality across every page. The previous font stack used system fonts (-apple-system, BlinkMacSystemFont, Segoe UI) which provide fast loading but inconsistent rendering across platforms. The portfolio targets a professional audience that evaluates attention to detail — typography is a signal of design sensibility. The requirements: a sans-serif family with excellent readability at small sizes (13-14px for metadata), strong weight contrast (400-800) for visual hierarchy, a monospace companion for technical content, and variable font support for optimal file size. The font must align with the site's technical positioning within the Next.js/Vercel ecosystem.

Decision

Adopt the Geist font family (Geist Sans + Geist Mono) as the exclusive typographic foundation. Geist Sans serves all body text, headings, and UI elements. Geist Mono serves code snippets, ADR numbers, and technical metadata. Both are loaded as variable fonts via next/font/local, enabling the full weight range (100-900) from a single file per family. Font display is set to 'swap' to prevent invisible text during load. The font files are self-hosted from the Next.js build output — no external font service dependency.

Consequences

Positive: Variable fonts reduce total typographic payload from ~120KB (multiple static weight files) to ~35KB (two variable files). Optical sizing built into Geist ensures consistent readability from 11px metadata labels to 48px hero headings without manual per-size adjustments. The monospace companion (Geist Mono) shares design DNA with the sans-serif, creating visual cohesion between prose and code. Self-hosting via next/font eliminates render-blocking external requests to Google Fonts or similar CDNs. The font's association with the Vercel ecosystem subtly reinforces the site's technical identity. Negative: Geist is less universally recognized than Inter, Roboto, or system fonts — some visitors may perceive it as unfamiliar. The variable font files require browser support for the CSS font-variation-settings spec (supported in all modern browsers, but not IE11). Self-hosting means no benefit from cross-site font caching that Google Fonts provides. These are acceptable trade-offs for a site that prioritizes typographic precision and self-contained performance over broad familiarity.

Calibrated Uncertainty

Predictions at Decision Time

Expected Geist to provide a measurable improvement in typographic consistency across platforms (macOS, Windows, Linux). Predicted the variable font payload reduction (~85KB saved) would positively impact LCP and FCP metrics. Assumed the font's association with Vercel would be recognized by the target audience (developers, technical hiring managers) as a positive signal. Predicted no readability issues at small sizes (11-13px) based on Geist's optical sizing features.

Measured Outcomes

Cross-platform consistency improved dramatically — particularly on Windows, where system fonts (Segoe UI) rendered noticeably differently from macOS (SF Pro). Geist renders consistently across all tested platforms. The payload reduction contributed to a ~50ms improvement in LCP on mobile connections. Small-size readability at 11px (metadata labels) and 13px (secondary text) is excellent — the optical sizing handles the weight distribution well. The Vercel ecosystem association is subtle: no one has explicitly commented on the font choice, but the overall visual quality of the site has drawn positive feedback. The unexpected benefit: Geist Mono is excellent for the ADR number badges and technical metadata, creating a consistent 'technical document' feel.

Unknowns at Decision Time

Did not know whether Vercel would continue actively developing and maintaining Geist, or whether it would become a static release. As of February 2026, Geist remains under active development with regular updates. Also unknown: whether the font pairing (Geist Sans + Geist Mono) would work aesthetically at all sizes and contexts. It does — the shared design DNA was not just marketing; the fonts genuinely complement each other. Unknown at decision time: whether next/font/local would handle variable font files correctly without FOUT in all deployment scenarios. It works flawlessly on Vercel.

Reversibility Classification

Two-Way Door

Switching fonts requires updating the next/font/local configuration (2 files), the GlobalStyle font-family declarations, and any component that explicitly references var(--font-geist-mono). The styled-components theme doesn't encode font families directly, so the change is localized to the font configuration layer. Estimated effort: 1-2 hours for a complete font swap. The most time-consuming part would be visual review across all pages to verify the new font's metrics at every size.

Strongest Counter-Argument

Inter is the most widely adopted web font in the developer tools ecosystem (used by Vercel's own dashboard, Linear, Raycast, and dozens of dev tools). It has broader Unicode support, more extensive testing across platforms, and higher community familiarity. Choosing Inter would have aligned the portfolio with the broader developer tooling aesthetic rather than the narrower Vercel ecosystem. System fonts remain the highest-performance option — zero font payload, instant rendering, and native platform feel. The counter-counter: Geist's monospace companion (Geist Mono) is the decisive advantage — Inter's recommended monospace pairing (JetBrains Mono) doesn't share design DNA, creating a subtle visual disconnection between prose and code.

Technical Context

Stack
Geist SansGeist Mononext/font/localVariable Fonts
Font Payload
~35KB total (2 variable files)
Previous Payload
~120KB (multiple static files)
Weight Range
100-900
Font Display
swap
Constraints
  • No external font CDN dependency
  • Variable font browser support required
  • Self-hosted from build output

Related Decisions