Skip to content

ops(frontend): self-host fonts via @fontsource — eliminates build-time Google Fonts dependency#98

Merged
dackclup merged 1 commit into
mainfrom
ops/selfhost-ibm-plex-sans
May 17, 2026
Merged

ops(frontend): self-host fonts via @fontsource — eliminates build-time Google Fonts dependency#98
dackclup merged 1 commit into
mainfrom
ops/selfhost-ibm-plex-sans

Conversation

@dackclup
Copy link
Copy Markdown
Owner

@dackclup dackclup commented May 17, 2026

Summary

PR #96 CI run #249 (docs(phase4.5c) merge to main) failed the Frontend (build) job with:

NextFontError: Failed to fetch `IBM Plex Sans` from Google Fonts.
  at app/layout.tsx — IBM_Plex_Sans({subsets: ['latin'], weight: ...})

A transient Google Fonts network blip during CI build broke next/font/google. The very next CI run (PR #97 4.5d) went green — so the failure was a flaky external service, not a code regression. Production was unaffected (compute-rankings.yml runs independently of ci.yml).

This PR closes the door on that failure mode for good by switching all 3 fonts from next/font/google to @fontsource/* (SIL Open Font License — official OFL distribution channel).

Changes

File Change
frontend/package.json + @fontsource/ibm-plex-sans @fontsource/jetbrains-mono @fontsource/instrument-serif @ ^5.2.8
frontend/app/layout.tsx Drop next/font/google imports + the className={...variable} stack on <html>. CSS variables now declared in globals.css.
frontend/app/globals.css + 9 @import '@fontsource/*' lines (Plex 400/500/600/700 + JetBrains 400/500/600 + Instrument 400 normal + italic — exactly matches prior config). + 3 new CSS-variable declarations so existing consumers continue working.

Backward compat

  • All consumers (Tailwind utility classes, StockLogo.tsx inline fontFamily: 'var(--font-mono)', globals.css base-style font-family rules) read the same CSS-variable names — no rename ripple-through.
  • Font-display: @fontsource defaults to font-display: swap matching prior display: 'swap'.
  • Bundle size: +~140KB woff2 (vs the previous Google Fonts CDN fetch); negligible on the static export.

Verification

  • next build — 506 static pages, no NextFontError
  • tsc --noEmit — clean
  • Build offline-capable (no external font fetch)

Why @fontsource not vendored woff2 files

  • @fontsource is the OFL-compliant official source
  • Updates ship via npm update if the upstream projects release new revisions
  • No attribution / license risk vs hand-vendoring binary files

Not in this PR

  • npm audit warnings (5 vulns) are existing Next.js dep-tree issues per issue #41 (Next.js 14 → 16 bump) — not introduced here

Test plan

  • Vercel preview spot-check on mobile + desktop — font rendering identical to current production
  • CI Frontend (build) green — no NextFontError

https://claude.ai/code/session_015649aRyi2bvciQYZVNACd2


Generated by Claude Code

…e Google Fonts dependency

PR #96 CI run #249 (docs(phase4.5c) merge to main) failed the
Frontend (build) job with:

  NextFontError: Failed to fetch \`IBM Plex Sans\` from Google Fonts.
    at app/layout.tsx — IBM_Plex_Sans({subsets: ['latin'],
                                       weight: ['400','500','600','700'],
                                       display: 'swap',
                                       variable: '--font-ibm-plex-sans'})

A transient Google Fonts network blip during CI build broke
`next/font/google`. The very next CI run (PR #97 4.5d) went green
again — so the failure was a flaky external service, not a code
regression. Production was unaffected (compute-rankings.yml runs
independently of ci.yml).

This commit closes the door on the failure mode for good by
moving all 3 fonts from `next/font/google` to `@fontsource/*`
npm packages (SIL Open Font License, OFL — free to redistribute):

- `@fontsource/ibm-plex-sans` @ ^5.2.8
- `@fontsource/jetbrains-mono` @ ^5.2.8
- `@fontsource/instrument-serif` @ ^5.2.8

@fontsource bundles the woff2 files into node_modules, so the
Next.js build never touches an external host.

## Changes

| File | Change |
|---|---|
| `frontend/package.json` | + 3 `@fontsource/*` dependencies (and corresponding `package-lock.json` entries) |
| `frontend/app/layout.tsx` | Drop `next/font/google` imports (`IBM_Plex_Sans`, `JetBrains_Mono`, `Instrument_Serif`). Drop the `className={...variable}` stack on `<html>`. CSS variables now declared in globals.css. |
| `frontend/app/globals.css` | + 9 `@import '@fontsource/*'` lines (Plex 400/500/600/700, JetBrains 400/500/600, Instrument 400 normal + italic — exactly matches the prior next/font config). + 3 new CSS variable declarations (`--font-ibm-plex-sans`, `--font-jetbrains-mono`, `--font-instrument-serif`) so existing `--font-sans/mono/serif` chains keep resolving the same fallback stack. |

## Backward compat

- All existing consumers (Tailwind utility classes,
  `StockLogo.tsx`'s inline `fontFamily: 'var(--font-mono)'`,
  globals.css base-style font-family rules) continue to read
  the same CSS variable names — no rename ripple-through.
- Font-display behavior: @fontsource defaults to `font-display:
  swap` which matches the previous `display: 'swap'` config.
- Bundle size impact: +~140KB woff2 files (vs the previous
  Google Fonts CDN fetch). Negligible on the static export; the
  resilience win outweighs the size cost.

## Verification

- ✅ `next build` — 506 static pages built; no NextFontError
- ✅ `tsc --noEmit` — clean
- ✅ No external font fetch in build logs (verified via build output)
- ✅ Build offline-capable from now on

## Why @fontsource not vendored woff2 files

- @fontsource packages are the OFL-compliant official source
- Updates ship via `npm update` if the IBM Plex / JetBrains /
  Instrument projects release new revisions
- No license/attribution risk vs hand-vendoring binary files

## Not in this PR

- npm audit warnings (5 vulns, 1 critical) are in the existing
  Next.js dep tree per issue #41 (Next.js 14 → 16 bump). Not
  introduced by this PR; tracked separately.

https://claude.ai/code/session_015649aRyi2bvciQYZVNACd2
@vercel
Copy link
Copy Markdown

vercel Bot commented May 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
quantrank Ready Ready Preview, Comment May 17, 2026 5:26am

@dackclup dackclup marked this pull request as ready for review May 17, 2026 05:28
@dackclup dackclup merged commit 0fcda53 into main May 17, 2026
4 checks passed
@dackclup dackclup deleted the ops/selfhost-ibm-plex-sans branch May 17, 2026 05:28
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.

2 participants