Pond fonts: catalog build, admin UI, and application #66
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#66
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Per-pond font selection with self-hosted Google Fonts is a distinctive vision feature (ADR 0016) and a prerequisite for faithful PDF export.
Scope
Implement the font catalog build step (
deploy/fonts/: pinned download of ~15 OFL/Apache families as WOFF2 subsets into the web image, license records, generated @font-face CSS), the pond settings 'Appearance' section (three slots: heading/body/mono with live preview, defaults Roboto 400 / Roboto 200 / Fira Code), application via CSS variables on the pond root, and the catalog attribution page.Acceptance criteria
Technical notes
font-src 'self').Dependencies
Depends on #21, #52.
Size: ~1.5 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Done in
f500198. Pipeline fully green (all 7 contexts, incl. the new fonts e2e pack); deployed to Test + Int and verified live.What shipped (ADR 0016)
deploy/fonts/build-fonts.mjsvalidates every entry has license info (fails the build otherwise), downloads the WOFF2 weights intoapps/web/public/fonts/(gitignored), and generates the@font-facestylesheet — run at image build time from the web Dockerfile (with retries), never from a visitor's browser.PondFontScopesets--font-heading/body/mono(+ weights) frompond.settings.fontson the editor + read view; the app-wide CSS already reads those custom properties, so headings/body/code re-resolve to the pond's fonts. A pond with no settings arrives defaulted (Roboto 400 / Roboto 200 / Fira Code), so the vision defaults always render.fontsadded toupdatePondInputSchema, merged inPondsService.update); a font catalog attribution page (/fonts) listing families + licenses. Newfonti18n namespace (de+en).Content-Security-Policyin nginx.conf (default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; …).Acceptance criteria
font-src 'self'andcatalog.css(53@font-face) references only/fonts/…, zero third-party URLs./fontspage +build-fonts.mjsvalidation + a shared catalog-integrity unit test.Tests: shared
fonts.test.ts(the catalog invariants the build enforces) + e2efonts.spec.ts(3 cases). Quality bar green: typecheck, lint, i18n, api 213, web 50, shared 126.Live verification: Test + Int serve the CSP header (
font-src 'self'),/fonts/catalog.css(53 faces, 0 off-origin URLs), and real WOFF2 (roboto-400.woff2, validwOF2). The Appearance API persists a font change (Int). CD smoke tests green — the CSP does not break the app. The web image build downloaded the catalog fonts from upstream successfully.Next: #67 (PDF export via Gotenberg — a new sidecar, provisioned like pandoc; inlines the pond's fonts, ADR 0009/0016).