Decision record
ADR-0002: UI framework and styling strategy
ADR-0002: UI framework and styling strategy
Status: accepted · Date: 2026-08-27
Decision
Tailwind CSS v4 + shadcn-svelte-style components (Bits UI primitives) vendored into
packages/ui, with design tokens as CSS custom properties defined once in
packages/ui/src/tokens.css (normative source: DESIGN.md) and mapped into
Tailwind’s @theme namespace by apps/web. Rendered document content is styled
by the semantic .bladbase-prose stylesheet only — utility classes never enter
stored document HTML.
Context
The product needs a dense, quiet, keyboard-first UI (Outline/Docmost class) with heavy customization of editor chrome, page tree, and command palette. Most polished component libraries are React-only; the SvelteKit choice constrains us to Svelte-native options.
Alternatives considered
- Skeleton UI: batteries included, but its opinions would be fought in every customized surface.
- DaisyUI: fastest start, generic look, hard to bend into a distinctive product.
- Hand-rolled CSS only: full control but re-implements focus/ARIA behavior that Bits UI provides.
Consequences
- Vendored components are project source: edited freely, no upstream merges.
- Tokens are framework-neutral, so the Astro marketing site consumes the same palette without Svelte.
- Anything with focus management or ARIA semantics builds on Bits UI primitives (vendored on demand from Phase 1 onward), not raw DOM handlers.
- Two-layer styling boundary is enforced by rule: Tailwind utilities for app
chrome,
.bladbase-prosefor document content — the exports pipeline depends on it (PLAN Phase 4 standalone-render test).
References
- Svelte runes
- Bits UI — the headless primitives vendored here