laywill / laywill/laywill.github.io
Re-vendor fonts and switch back to the local provider for hermetic builds
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 0
- Forks
- 0
- Avg merge
- 8h 17m
- Merged PRs (30d)
- 58
Description
Re-vendor the WOFF2 font files and switch astro.config.mjs from fontProviders.google() back to fontProviders.local(), so production builds stop depending on a third-party font CDN at build time.
Background
#47 (closing #24) originally vendored three Latin-subset WOFF2 binaries in src/assets/fonts/ and resolved them with the local provider, on a hermetic-build argument. That was deliberately reversed in that PR: the binaries were deleted and the faces are now resolved by fontProviders.google() at build time.
The reasoning was phase-appropriateness, not a judgement that vendoring is wrong. While the design study is still running, the font set, the weights and possibly the families themselves will churn, and every such change means re-subsetting and re-committing binaries by hand. That cost is worth paying once the typography is locked — not while it is still moving.
This is the issue that pays it back.
What this is not
It is not a privacy or "stop using Google Fonts" fix. That requirement is already met and is unaffected by the provider choice: a remote provider resolves at build time, so Astro downloads the faces during astro build and emits them fingerprinted into our own origin. Both providers were built and compared during #47 — identical @font-face rules, identical metric-adjusted fallback faces, identical Latin unicode-range, identical preloads, and zero gstatic/googleapis references in dist/ either way.
What this issue buys is narrower and worth stating plainly so it can be judged on its merits at the time:
- Hermetic builds. A release build stops needing network to reach a font CDN. It will still need network for
npm ci. - Auditable bytes. The exact files served are reviewable in-repo and change only via a reviewed commit.
- Insulation from upstream drift. Google re-cutting a face can't silently change what the site serves between two builds of the same commit.
Blocked until all epics are complete
The typography is not settled until the design work and everything that consumes it has landed, so this is gated on the full epic set:
- #38 — Epic E1: Repo foundation
- #39 — Epic E2: Astro scaffold
- #40 — Epic E3: Design
- #41 — Epic E4: Content
- #42 — Epic E5: Notes
- #43 — Epic E6: SEO, analytics, launch
#40 is the one that actually locks the face/weight set (via #26 and #27), but content and Notes can still surface a weight or an italic nothing had needed before — #33's Obsidian-flavoured elements especially. Doing this before #43 means redoing it.
Why the reversal is cheap
Components only ever reference the semantic --font-display / --font-body / --font-mono tokens in src/styles/tokens.css; nothing outside astro.config.mjs knows a font file path. The switch should touch the config, the vendored files, and the docs — nothing else. If it turns out to touch a component, that's a token-indirection leak worth fixing separately.
Two options
- Vendor the WOFF2 files in
src/assets/fonts/— what #47 originally did. Fully self-contained; requires hand re-subsetting on any change. - Pin
@fontsource/*packages and point thelocalprovider atnode_modules— keeps the binaries out of git while making the bytes integrity-hashed inpackage-lock.json, and makes weight changes a dependency bump instead of a manual subsetting job. Not tested; a build with no network still needs a warm npm cache either way.
Option 2 is probably the better end state, but pick at the time.
Acceptance criteria
-
astro.config.mjsusesfontProviders.local()for all families - Only the weights and styles the built site actually renders are vendored — no speculative extras
-
astro buildsucceeds with the font CDN unreachable (verify by blocking it, not by assuming) -
dist/output is equivalent to thegoogle-provider build: same fingerprinted files per face, metric-adjusted fallback faces present, correct preloads, zerogstatic/googleapisreferences - Latin
unicodeRangeis still declared, and its source (generated vs hand-written) is noted in a comment — #47 removed a hand-maintainedLATIN_SUBSETconstant precisely because the provider generated the identical range -
public/fonts/LICENSE-*.txtstill present and still matching the shipped faces (SIL OFL requires the licence to travel with the redistributed fonts — this obligation is independent of where the source files live) -
docs/overhaul/typography.md"Loading rules" updated. Keep the distinction it now draws — self-hosting is about what the visitor's browser fetches, not what git tracks — since conflating the two is what caused the original churn - CI builds the site (see #49 and the missing
npm run buildworkflow), so a font-resolution failure is caught rather than shipped
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
First review astro.config.mjs, the existing font assets under src/assets/fonts/, and docs/overhaul/typography.md after the typography epics settle the families, weights, and styles. Run astro build with the font CDN blocked, then compare dist/ output, licenses, unicode ranges, and preloads; also inspect the missing npm run build workflow associated with #49.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, javascript
- Domain
- build-system, ci-cd, documentation
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100