Establish the design system and the UX-engineering function

0010-design-system-and-ux-function

decision read as Explain confidence asserted status active 2026-06-14 owner ux-engineer
Reversibility
two-way door

DEC-0010 — Design system & UX-engineering function

Context

The moat (extraction → OKF graph, DEC-0008/0009) exists in code, but a client's institutional memory has no face yet. DEC-0005 deferred a "frontend/docs agent" on the grounds that output rendering is one downstream surface, not the product. That reasoning holds for the docs site/app — but it conflates two things. The surface is downstream; the design language any surface consumes is foundation. Without it, every future surface re-invents color, type, and spacing, and the index.how-grade polish bar (the stated UX gold standard) is unreachable.

Options considered

  1. Keep deferring until a docs surface is chosen — accept ad-hoc styling later.
  2. Adopt an off-the-shelf UI kit (e.g. a Tailwind/shadcn stack) as the system.
  3. Build a tokens-first, framework-agnostic design system now + a UX-engineer subagent to own it.

Decision

Option 3. Ship packages/design (@dossier/design) — a leaf package (zero deps, like the @dossier/okf keystone) — and add the ux-engineer subagent.

  • Tokens are the record; CSS is a cache. Typed token tree in TS is the single source of truth; styles/dossier.css is generated by renderCss() and a drift test fails if they diverge — the OKF philosophy applied to design.
  • Two-tier color: primitives (the only hex literals) → intent-named semantic roles. Light + dark are structurally identical (enforced by the ColorRoles type) and honor prefers-color-scheme.
  • The design language: warm-paper neutrals + a clay/terracotta signature accent; editorial serif over humanist sans over mono; calm motion; soft warm elevation. Every OKF concept type gets a signature hue (decision wears the clay — captured judgment is the IP).
  • Framework-agnostic delivery: plain CSS variables + ds--prefixed component classes in @layer cascade layers. Any Vite-based surface (Starlight/VitePress) or a React app consumes the same stylesheet and tokens.

Rationale

  • Sovereignty extends to the UI. Portable CSS + tokens, no proprietary SDK — a client can render their OKF repo with plain files. Off-the-shelf kits (Option
    1. bind the look to a framework and a utility dialect, the opposite of DEC-0001.
  • Single-source-of-truth, atomic — the bar from CLAUDE.md. Tokens defined once, derived everywhere; the drift test makes that a guarantee, not a habit.
  • Foundation unblocks surfaces. Deciding the generator (Starlight vs. VitePress) is still deferred and now cheap — both run on Vite and consume this system unchanged.
  • Claude-primitives-first (DEC-0004): the function ships as a subagent, like the rest of the roster.

Consequences

  • DEC-0005's deferral of a frontend function is lifted: the roster gains ux-engineer (activates next session start, like all subagents/hooks).
  • A change to any token requires re-running build:css and committing the regenerated stylesheet; CI's drift test enforces it.
  • The docs-site/app surface choice remains explicitly deferred — this decides the design language, not the renderer.
  • Accessibility (WCAG AA contrast, focus, reduced-motion) is encoded in the tokens and is now a maintained invariant.

Review

Revisit when the first OKF-rendering surface is chosen: confirm the token API and component set survive a real reading experience (concept pages, provenance, typed-edge navigation) without forking the system.