Skip to content

perf(starter): cache fonts and add metric-matched fallbacks - #54

Merged
Madraka merged 1 commit into
mainfrom
perf/font-cache-and-fallbacks
Oct 21, 2026
Merged

Madraka merged 1 commit into
mainfrom
perf/font-cache-and-fallbacks

Conversation

@Madraka

@Madraka Madraka commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Reloading a site redrew its text when the web fonts arrived (layout shift). Two causes, both fixed:

  1. No cache: /fonts/* was served with max-age=0, must-revalidate, so every reload waited ~400–650 ms for the fonts. They now live under /fonts/v1/ and public/_headers caches them a year, immutable (a new font set gets /fonts/v2/).
  2. Mismatched fallback: the system font shown before the swap had other metrics. scripts/font-fallbacks.ts generates font-fallbacks.css: one local() fallback per web font with size-adjust and ascent/descent/line-gap overrides (Next.js / Fontaine maths, metrics read with Capsize), listed right after each web font in the pairing stacks. Fraunces and Source Sans 3 carry a measured width correction (their variable default instances differ from body text).

Measured in Chrome (640 px paragraph, 17 px): height difference from the web font is 0.0% for all six fonts (plain system fonts: −11% to −26%), widths within 1.2%.

Also: render_page / cloudhal render gain a font-fallback check; pnpm check and CI fail if the generated CSS is stale.

Existing sites keep their copied starter files; new sites get the fix.

🤖 Generated with Claude Code

Reloading a starter site redrew its text when the web fonts arrived: the
font files were revalidated on every load (max-age=0), and the system font
shown meanwhile had other metrics, so the swap moved the text.

- Fonts move to /fonts/v1/ and public/_headers caches them a year, immutable.
- scripts/font-fallbacks.ts generates font-fallbacks.css: one local fallback
  face per web font (size-adjust, ascent/descent/line-gap overrides, read with
  Capsize), listed right after it in the pairing stacks. Measured in Chrome,
  paragraph heights match the web fonts exactly (system fonts were 11-26% off).
  `pnpm check` and CI fail when the file is stale.
- render_page / cloudhal render: new font-fallback check for web fonts with
  no metric-matched fallback after them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka
Madraka merged commit 6c9c9b5 into main Oct 21, 2026
6 checks passed
@Madraka
Madraka deleted the perf/font-cache-and-fallbacks branch October 21, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant