Skip to content

ADR-034 — Math rendering: KaTeX server-rendered at build

Status · Accepted Date · 2026-05-07 Closes · RFC-011 (with ADR-035, ADR-036) TA anchor · §components / primary-route-pages Related · PRD-008, ADR-014 (CI + GitHub Pages), ADR-016 (build-time assets), ADR-017 (i18n)

Context

PRD-008 / GitHub #39 introduce /science: an in-app encyclopedia covering ~40 physics concepts with formulas, diagrams, and prose. RFC-011 OQ-1 asked how to render math in section bodies. Four candidates: KaTeX server-rendered, KaTeX client-side, MathJax v3, hand-rolled SVG per formula. The trade-off pivots on bundle weight vs. authoring ergonomics.

Decision

Render path (RFC OQ-1 — Option A)

Use KaTeX to compile every formula_latex field into HTML at SvelteKit prerender time. The client receives static HTML + KaTeX's CSS only; the JavaScript library never ships to the browser.

Implementation:

  • Add katex@^0.16 as a runtime dependency and @types/katex as devDependency.
  • src/lib/katex.ts exposes renderKatex(latex: string): string — server-only helper called from +page.server.ts load functions during prerender.
  • KaTeX's CSS imported once at the science layout level (src/routes/science/+layout.svelte) so the fonts + glyphs are available offline.
  • LaTeX source authored in section JSON: { "formula_latex": "v = \\sqrt{\\mu \\cdot (2/r - 1/a)}" }.
  • The SvelteKit prerender = true directive on /science/[tab]/[section] ensures every section is a static HTML file — KaTeX never runs in the browser.

Edge cases (RFC OQ-1 — Option D fallback)

For any formula that KaTeX cannot render (e.g. macros KaTeX rejects, custom layout), inline an SVG into the section's formula_svg field instead. Schema treats formula_latex and formula_svg as mutually exclusive optional fields.

Budget

  • KaTeX CSS: ~30 KB minified gzipped, loaded once for the entire /science tree.
  • KaTeX JS: 0 KB at runtime (server-rendered).
  • Authored formulas: LaTeX strings in JSON; ~10–20 across all 40 sections.

Consequences

Positive: Authoring ergonomics of LaTeX without runtime cost. The encyclopedia can include rigorous formulas (vis-viva, Tsiolkovsky, orbital period) without inflating the JS bundle. Offline-capable per ADR-029 (PWA).

Negative: Build time grows by the cost of running KaTeX over every formula_latex field — negligible at 40 sections, observable at 400+. Edge-case formulas need a separate SVG fallback path, which costs authoring time. KaTeX's CSS adds 30 KB to first paint of /science; trivially cached after.

Implementation notes

  • Renderer entry point: src/lib/katex.ts.
  • Component wrapper: src/lib/components/ScienceFormula.svelte accepts pre-rendered HTML + caption.
  • Validation: scripts/validate-data.ts ensures every section with a formula_latex field produces valid HTML at build time (compile + assert non-empty output).
  • Deferred: client-side render path (RFC-011 OQ-1 Option B) — kept available as a fallback if SvelteKit's prerender ever can't statically resolve a section, but never invoked in steady state.

Orrery — architecture documentation · MIT · No tracking