All documents

Applying it to an app

Install

  1. Copy styles/, lib/, components/, hooks/ into src/, and public/fonts/ + public/logos/ into public/. Keep the @/* alias pointing at src/ (examples/tsconfig.paths.json).
  2. Install the dependencies in examples/package.deps.json.
  3. PostCSS: copy examples/postcss.config.mjs. Tailwind v4 has no tailwind.config.* — the theme is @theme inline inside globals.css.
  4. Import styles/globals.css once, in the root layout, and set the two attributes on <html> (examples/layout.tsx).
  5. Set the brand: data-brand="iq|rei|roof" on <html> and DEFAULT_BRAND in lib/brand.ts. Same decision, written twice — once for the stylesheet, once for the logo.
  6. Wire the session if the app has auth (examples/session-provider.tsx). Skip it and everything still renders as an open deploy.
  7. List the tools in one PRODUCTS file (examples/products.ts), then mount SiteShell in each tool's layout (examples/tool-shell.tsx).

Re-skinning an existing app

Work in this order. Each step is shippable on its own.

  1. Tokens first. Drop in styles/, point the app's existing CSS variables at the new ones, and look at the app in both themes. Most of the change lands here.
  2. Type and icons. Fonts, the seven tiers, one icon library.
  3. Primitives. Replace buttons, inputs, selects, tables — one component at a time, starting with the one used most.
  4. The shell. The rail, the header, the switcher. This is the step a reader notices; do it after the primitives so the inside already matches.
  5. The devices. Eyebrow, Callout, StatTile, Panel — the marks that make it read as ours rather than as generic shadcn.
  6. Delete. Old variables, old one-off components, the second icon pack, the third radius. A design system that runs alongside the thing it replaced is two design systems.

Done means

  • Both themes render correctly on every screen, including popovers, menus and empty states. Flip data-theme and look.
  • Every colour on screen resolves to a token. Search the diff for # and rgb( and justify each hit.
  • One font stack per role, three families total, and the woff2 files are actually being served.
  • One icon library. No emoji as icons.
  • Every interactive control shows a visible focus ring and has a 44px hit target.
  • Every figure is mono and tabular; every counting column says what it counts.
  • One primary button per surface.
  • Any screen that writes has the gate, the refusal sentence, the failure alert, and enforcement on the server side too.
  • data-brand produces a correct app in all three brands. Switch it to rei and roof, look, switch it back.
  • Type checks clean, and the CSS compiles.

When something is not covered here

Ask rather than invent. The answer is usually "there is a token for that" or "that decision has a reason in 10-rules.md". If it genuinely is new, write it down in these docs at the same time you build it — that is how this file got to be worth reading.