# Fonts — provenance Self-hosted per `docs/02-design-system.md`. **No runtime Google Fonts request**: the page collects legal inquiries, and a third-party font call costs a round trip and adds a third party to that page. These `.woff2` files are committed rather than pulled at build time so their paths are stable — a `` needs a filename that does not change between builds, and Astro's asset hashing would break that. | File | Source package | Version | Licence | |---|---|---|---| | `instrument-serif-latin-400-normal.woff2` | `@fontsource/instrument-serif` | 5.3.0 | SIL OFL 1.1 | | `instrument-serif-latin-ext-400-normal.woff2` | `@fontsource/instrument-serif` | 5.3.0 | SIL OFL 1.1 | | `instrument-serif-latin-400-italic.woff2` | `@fontsource/instrument-serif` | 5.3.0 | SIL OFL 1.1 | | `geist-latin-wght-normal.woff2` | `@fontsource-variable/geist` | 5.3.0 | SIL OFL 1.1 | | `geist-latin-ext-wght-normal.woff2` | `@fontsource-variable/geist` | 5.3.0 | SIL OFL 1.1 | | `geist-mono-latin-wght-normal.woff2` | `@fontsource-variable/geist-mono` | 5.3.0 | SIL OFL 1.1 | **The `?v=1` on every font URL is load-bearing.** `scripts/deploy-local.sh` serves `/fonts/*` with `max-age=31536000, immutable`, so a returning visitor holds these bytes for a year and no CloudFront invalidation can reach their browser cache. Replacing a file means bumping that query — in `src/styles/global.css` **and** in the `` in `BaseLayout.astro`, which must match character for character or the preload fetches a second copy instead of warming the cache. Fetched 2026-08-26 with `npm pack @5.3.0` and extracted from `package/files/`. Subsetting is Fontsource's, not ours — the `latin` and `latin-ext` cuts are exactly the "Latin + Latin Extended-A" the design system asks for. **123,804 bytes across all six**, of which only two — Instrument Serif 400 latin (21,032) and Geist latin (29,400) — are preloaded, so first paint pulls about 50 kB. Quote the byte figure, not `du -sh`, which reports 136K because it counts disk blocks rather than what crosses the wire. **Not covered by `AGENTS.md` R11.** R11 re-checks npm pins for currency and advisories; these are static binaries with no runtime and no dependency tree. Refresh them deliberately — when a face gains glyphs the site needs — by repeating the `npm pack` above, not on a currency schedule. **Deliberately absent:** the `latin-ext` italic cut of Instrument Serif, and every non-Latin cut of all three faces. `.display .it` is one italic phrase in a headline (`docs/02`), and D4 makes the site English-only. Add a cut when a page needs it; do not add all of them pre-emptively.