dorfteich/docs/architecture/adr/0016-self-hosted-fonts.md
Claude Fable 5 0629411966 Add architecture documentation, ADRs, and operations concept
Initial deliverable of the architecture phase: 16 ADRs (stack, CRDT
collaboration, plugin sandbox, import/export, backups, CI/CD), data
model, permission model, real-time collaboration and plugin concepts,
deployment/operations/security documentation, and the milestone roadmap
that the implementation issues are derived from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:36:16 +02:00

48 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR 0016: Self-hosted Google Fonts, per-pond font configuration
- Status: accepted
- Date: 2026-07-04
## Context
The vision: Pond Admins choose fonts for headings, body text, and monospace
from a set of free Google Fonts; fonts must be served from the instance
itself (never from Google's CDN) to avoid GDPR issues. Defaults: Roboto 400
(headings), Roboto 200 (body), Fira Code (monospace).
## Decision
- **Curated font catalog**: the repo contains a maintained list (~1525
families) of OFL/Apache-licensed families with the needed weights. A build
step (`deploy/fonts/`) downloads the WOFF2 files **at image build time**
from google-webfonts-helper/upstream sources and bakes them into the `web`
image under `/fonts/<family>/`. No runtime download, no third-party
requests from visitors' browsers — CSP allows `font-src 'self'` only.
- **Per-pond configuration**: pond settings store three font slots
(`heading`, `body`, `mono`), each referencing a catalog entry + weight.
The app applies them as CSS custom properties
(`--font-heading`, `--font-body`, `--font-mono`) on the pond's root
element; `@font-face` rules for the catalog are generated once.
- Defaults per vision: Roboto 400 / Roboto 200 / Fira Code. (Roboto 200 is
provided via the variable font or the 200 static weight; fallback stack
`system-ui` chain.)
- Licensing: each catalog entry records its license (OFL/Apache); the
catalog page in the app shows attribution.
- Exports: the PDF renderer (ADR 0009) inlines the pond's fonts so PDFs
match the on-screen look.
## Consequences
- Adding a font is a catalog PR + image rebuild — no runtime font
management surface (deliberately small attack/complexity surface).
- Image size grows by a few MiB per family (WOFF2, subset to latin/latin-ext
by default) — negligible.
## Alternatives considered
- **Runtime font download by the server on admin selection**: flexible but
adds an outbound dependency, cache invalidation, and licensing bookkeeping
at runtime; rejected for v1.
- **Arbitrary font upload by Pond Admins**: licensing risk and file-format
attack surface; may become a Site-Admin-level feature later.