Ship Geist as WOFF2

Performancekamo-internal
Shipped
August 26, 2026 at 4:22 AM UTC
Author
kamo
Commit
aa02328

Both faces are preloaded on every route, so the format is paid on every first visit. 134,132 B of WOFF became 112,252 B of WOFF2 — 21,880 B, a 16% cut. That is smaller than the ~30% a WOFF2 conversion is usually quoted at, and the reason is worth writing down so nobody re-does this expecting more: the 30% figure is against uncompressed TTF. WOFF is already zlib-compressed, so what WOFF2 adds here is brotli plus the glyf/loca transform, not compression where there was none. Converted by decoding each WOFF container back to bare sfnt and re-encoding. Verified lossless by round-tripping the result: all 17 tables present in both faces, and `fvar` (the variable axes — these are variable fonts carrying the whole 100-900 range), `name` and `STAT` byte-identical. The build emits both faces and `next/font/local` accepts them. The preload stays. Dropping it was suggested during the audit and is a real regression: Geist Mono would fall back to the generic monospace stack on first paint. The converter was installed outside the project (`npm --prefix /tmp`), so package.json and the lockfile are untouched — worth doing that way in a repo where several sessions are editing at once. WOFF2 is universal in every evergreen engine since 2016 and ~98.5% globally; this app runs Next 16 and React 19, which do not support anything older. The .woff files are removed rather than kept as a fallback, since a second `src` would have to be declared and would only ever serve a browser the framework already refuses. Verified: production build succeeds and emits both faces; tsc --noEmit clean; all 10 guards pass.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing