laywill / laywill/laywill.github.io

Re-vendor fonts and switch back to the local provider for hermetic builds

Open
#51 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

infra
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

  1. Vendor the WOFF2 files in src/assets/fonts/ — what #47 originally did. Fully self-contained; requires hand re-subsetting on any change.
  2. Pin @fontsource/* packages and point the local provider at node_modules — keeps the binaries out of git while making the bytes integrity-hashed in package-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.mjs uses fontProviders.local() for all families
  • Only the weights and styles the built site actually renders are vendored — no speculative extras
  • astro build succeeds with the font CDN unreachable (verify by blocking it, not by assuming)
  • dist/ output is equivalent to the google-provider build: same fingerprinted files per face, metric-adjusted fallback faces present, correct preloads, zero gstatic/googleapis references
  • Latin unicodeRange is still declared, and its source (generated vs hand-written) is noted in a comment — #47 removed a hand-maintained LATIN_SUBSET constant precisely because the provider generated the identical range
  • public/fonts/LICENSE-*.txt still 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 build workflow), so a font-resolution failure is caught rather than shipped

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.