Skip to content

feat(shell-ui): vendor Commissioner + Fraunces web fonts locally (offline/CSP)#268

Merged
stuffbucket merged 1 commit into
mainfrom
feat/vendor-web-fonts
Jul 7, 2026
Merged

feat(shell-ui): vendor Commissioner + Fraunces web fonts locally (offline/CSP)#268
stuffbucket merged 1 commit into
mainfrom
feat/vendor-web-fonts

Conversation

@stuffbucket

Copy link
Copy Markdown
Owner

What & why

The shipped UI still loaded its web fonts from fonts.googleapis.com — the last external asset dependency in the UI (Tailwind + Lucide are already vendored under shell/ui/dashboard/vendor/). This vendors the fonts too, so the webview never makes an external request: the app works fully offline and under a strict CSP, and it preserves the no-telemetry posture.

How

  • Fetched the variable-weight woff2 files Google's css2 endpoint serves for the exact axes the UI requested (Commissioner wght@200..900, Fraunces opsz,wght@9..144,300..900) using a modern browser UA. Captured the latin + latin-ext subsets so accented logins / model names render without falling back.
  • Dashboard — woff2 in shell/ui/dashboard/vendor/fonts/, @font-face added to style.css. Served verbatim (the dashboard vendor/ dir is already copied wholesale by the build). Commissioner only — the Dashboard has no Fraunces display moment (native titlebar carries the page name).
  • Settings — woff2 in shell/ui/settings/vendor/fonts/, @font-face in an inline <style> in index.html. scripts/build-ui.ts now copies the settings vendor/ dir into the bundle output so the bare relative url()s resolve at /ui/settings/vendor/fonts/* (Bun's HTML bundler leaves bare relative url()s untouched). Fraunces (display) + Commissioner (body).
  • Removed the fonts.googleapis.com <link rel="stylesheet"> from both index.html files. There were no preconnect links to remove.
  • Fonts served with Content-Type: font/woff2 (already mapped in web-content-types.ts); production embed picks them up automatically (gen-ui-embed.ts walks the whole dist tree).

woff2 files added (variable font, one per subset)

File Family / subset Size
commissioner-latin.woff2 Commissioner · latin 36,696 B
commissioner-latin-ext.woff2 Commissioner · latin-ext 30,840 B
fraunces-latin.woff2 Fraunces · latin 67,388 B
fraunces-latin-ext.woff2 Fraunces · latin-ext 59,540 B

Commissioner is vendored under both surfaces (dashboard + settings) since the build serves them independently; Fraunces only under settings.

Smoke — CDN hard-blocked

Headless Chrome against the freshly-built UI (via ui-harness, serving the real shell/dist), with fonts.googleapis.com and fonts.gstatic.com resolver-mapped to 0.0.0.0 (--host-resolver-rules). Both pages render the correct self-hosted faces — Fraunces headings + Commissioner body on Settings, Commissioner on Dashboard. Had the local woff2 failed to load, text would fall back to the generic Georgia / Segoe stack (visibly different). Level achieved: full offline / CDN-blocked render.

(The Dashboard's "Usage request failed 404" banner is a ui-harness limitation — the mock backend doesn't serve the token-usage endpoint — not a font issue; the Period selector + banner text render in Commissioner.)

Settings (CDN blocked)

settings

Dashboard (CDN blocked)

dashboard

Checks

  • bun run build:ui clean; shell tsc --noEmit clean (Bun.build doesn't typecheck)
  • bun run typecheck clean
  • bun run lint clean

…line/CSP)

The shipped UI still loaded web fonts from fonts.googleapis.com — the
last external asset dependency (tailwind + lucide are already vendored).
Vendor the fonts too so the webview never makes an external request:
works fully offline and under a strict CSP, and preserves the
no-telemetry posture.

- Downloaded the variable-weight woff2 files Google's css2 endpoint
  serves for the exact axes the UI requested (Commissioner wght@200..900,
  Fraunces opsz,wght@9..144,300..900), latin + latin-ext subsets.
- Dashboard: woff2 under shell/ui/dashboard/vendor/fonts/, @font-face
  in style.css, served verbatim (copied like the existing vendor/).
  Commissioner only — the Dashboard has no Fraunces display moment.
- Settings: woff2 under shell/ui/settings/vendor/fonts/, @font-face in
  an inline <style> in index.html; build-ui.ts now copies the settings
  vendor/ dir into the bundle so the bare relative url()s resolve.
  Both Fraunces (display) + Commissioner (body).
- Removed the fonts.googleapis.com <link rel="stylesheet"> from both
  index.html files. (No preconnect links existed.)

woff2 files (variable, one per subset):
  commissioner-latin.woff2      36,696 B
  commissioner-latin-ext.woff2  30,840 B
  fraunces-latin.woff2          67,388 B
  fraunces-latin-ext.woff2      59,540 B

Smoke: headless Chrome against the built UI (ui-harness) with
fonts.googleapis.com / fonts.gstatic.com resolver-mapped to 0.0.0.0
(hard-blocked). Both pages render the correct self-hosted faces —
Fraunces headings + Commissioner body on Settings, Commissioner on
Dashboard. Artifacts under .github/pr-artifacts/.
@stuffbucket
stuffbucket merged commit d1a56df into main Jul 7, 2026
4 checks passed
@stuffbucket
stuffbucket deleted the feat/vendor-web-fonts branch July 13, 2026 05:29
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.

1 participant