Applying it to an app
Install
- Copy
styles/,lib/,components/,hooks/intosrc/, andpublic/fonts/+public/logos/intopublic/. Keep the@/*alias pointing atsrc/(examples/tsconfig.paths.json). - Install the dependencies in
examples/package.deps.json. - PostCSS: copy
examples/postcss.config.mjs. Tailwind v4 has notailwind.config.*— the theme is@theme inlineinsideglobals.css. - Import
styles/globals.cssonce, in the root layout, and set the two attributes on<html>(examples/layout.tsx). - Set the brand:
data-brand="iq|rei|roof"on<html>andDEFAULT_BRANDinlib/brand.ts. Same decision, written twice — once for the stylesheet, once for the logo. - Wire the session if the app has auth (
examples/session-provider.tsx). Skip it and everything still renders as an open deploy. - List the tools in one
PRODUCTSfile (examples/products.ts), then mountSiteShellin each tool's layout (examples/tool-shell.tsx).
Re-skinning an existing app
Work in this order. Each step is shippable on its own.
- 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. - Type and icons. Fonts, the seven tiers, one icon library.
- Primitives. Replace buttons, inputs, selects, tables — one component at a time, starting with the one used most.
- 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.
- The devices. Eyebrow, Callout, StatTile, Panel — the marks that make it read as ours rather than as generic shadcn.
- 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-themeand look. - Every colour on screen resolves to a token. Search the diff for
#andrgb(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-brandproduces a correct app in all three brands. Switch it toreiandroof, 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.