ADR-002 — Docs theming strategy
Ride on Fumadocs @theme block to apply bassclef brand tokens without forking Fumadocs presets.
ADR-002 — Docs theming strategy
Status. Accepted 2026-08-23.
Authors. kingofrock + claude opus 4.7.
Full ADR. See architecture/decisions/ADR-002-docs-theming-strategy.md in the repo for the complete decision record including light-mode + dark-mode mapping tables, font mapping table, and runbook.
Context
PR #119 shipped docs-site/ with Fumadocs' default neutral theme — grayscale palette, system sans-serif fonts, black CTA button. Zero brand cohesion with the bassclef.dev landing, which uses tokens.css to render cream background, burnt-orange CTAs, Bricolage Grotesque headings, Fraunces serif body, and JetBrains Mono for code.
When Sam / Louis / Morgan navigate from bassclef.dev to docs.bassclef.dev, the visual break signals "different product" rather than "same brand, different section." That is a brand-cohesion defect worth fixing before adopter volume grows.
The load-bearing question: how do we apply bassclef brand tokens to the docs site without forking Fumadocs, without maintaining a fork of any Fumadocs preset, and without divergence between tokens.css (landing) and whatever the docs site consumes?
Decision
Ride on Fumadocs' @theme block. Map bassclef --bc-* tokens to Fumadocs --color-fd-* tokens in docs-site/app/global.css. Load bassclef fonts via next/font/google in docs-site/app/layout.tsx. Keep tokens.css at the repo root as the single source of truth; the docs site inherits the same values.
Three files carry the theming:
tokens.css(repo root) — bassclef design tokens (11 colors, 3 font families, 2 line dividers). Source of truth. Consumed by landing directly and by docs site via the mapping.docs-site/app/global.css— importsfumadocs-ui/css/neutral.css+preset.cssfor structural CSS, then@themeblock maps--bc-*→--color-fd-*for light AND dark modes.docs-site/app/layout.tsx—next/font/googleimports Bricolage Grotesque, Fraunces, JetBrains Mono. Wires--font-sans,--font-serif,--font-monoCSS variables onto<html>so Tailwind + Fumadocs pick them up.
Cream mode is the default. Dark mode auto-toggles via Fumadocs' .dark class. Both palettes read brand-correct.
Semantic callout tokens (info / warning / error / success / idea) stay at Fumadocs defaults for this cycle; a follow-on ADR retunes them if signal clarity surfaces as a problem.
Consequences
Easier: brand cohesion across landing → docs (Sam sees one visual identity); single source of truth for brand values in tokens.css (changes propagate to both surfaces); docs inherit Fumadocs component structure without forking anything.
Harder: any change to Fumadocs' --color-fd-* variable set upstream requires updating the mapping in docs-site/app/global.css; adopting a different Fumadocs preset would collide with the @theme override.
Unblocked: brand cohesion story for future adopters; dogfooding the ADR pattern on docs.bassclef.dev itself.
Blocked: none.
Rejected alternatives
Fork one of Fumadocs' 11 built-in presets (aspen, black, catppuccin, dusk, emerald, ocean, purple, ruby, shadcn, solar, vitepress). Rejected because: adds a maintenance surface for every Fumadocs UI upgrade; a bassclef-specific fork drifts from upstream faster than a @theme override.
Style at the component level (patch each Fumadocs component with brand-specific classes). Rejected because: violates the single-source-of-truth invariant; means every future Fumadocs component upgrade needs a re-patch; scales badly across 30+ components.
Skip theming entirely for now (accept Fumadocs neutral until brand becomes a bigger signal). Rejected because: brand cohesion between landing and docs is a Sam-lens concern already visible in the current visual break; the cost of adding a @theme block is ~30 lines.
Use CSS-in-JS or styled-components at the docs-site root. Rejected because: Fumadocs uses Tailwind v4 CSS-first theming; CSS-in-JS would fight the framework and lose the CSS-cascade benefits (dark mode toggle, media queries, etc.).
Exit cost
Small. Two files carry the mapping: docs-site/app/global.css (~30 lines of @theme block) and docs-site/app/layout.tsx (~15 lines of font imports). Removing the theme override means reverting these two files.
If bassclef ever swaps Fumadocs for a different framework, the brand tokens in tokens.css are portable (any framework can read CSS custom properties); only the mapping layer needs rewiring for the new framework's variable names.
If bassclef ever adopts a different Fumadocs preset, remove the @theme block and replace with the preset's import. Structural CSS (sidebar, TOC, code blocks) still works unchanged.