For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.

Theming

The token contract behind the foundation: color pairs, spacing steps, and radius.

The foundation is token-driven. Colors are CSS variables mapped to Tailwind utilities; spacing and radius are compiled from a TypeScript token scale. Nothing in a component hardcodes a hex value or a raw utility.

Color tokens

Colors follow the shadcn semantic-pairs contract: every surface token has a matching foreground token, declared as CSS variables on :root and bridged into Tailwind v4 through @theme inline:

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}
 
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.4386 0 0);
}

The pairs the primitives consume:

PairConsumed by
background / foregroundShell, Section, Box base surfaces
card / card-foregroundBox surface="card"
muted / muted-foregroundSection surface="muted", Box
primary / primary-foregroundSection surface="primary", Box
secondary / secondary-foregroundSection surface="secondary", Box

To re-theme, re-declare the variables in your own stylesheet after the base theme — components pick up the new values without any code changes. Inversion is consumption, not configuration: Section surface="inverted" renders bg-foreground text-background, so one palette powers both directions.

Spacing

Spacing is a TypeScript scale, not CSS variables. lib/tokens.ts defines the steps "0", "0.5", "1", "2", "2.5", "3", "4", "5", "6", "7", "8", "9", "10", "12", "14", "16", "20", "24" — the Tailwind spacing scale — and generates the class maps the layout family spreads into its variants:

export const gapClasses = spacingClasses("gap");
// { "0": "gap-0", "0.5": "gap-0.5", ..., "12": "gap-12", ..., "24": "gap-24" }

When you write <Stack gap="12">, the prop keys the map and the component renders gap-12. One step equals 4 pixels; sizeTokens exposes the pixel values for layout math. Because the keys are Tailwind step names, no arbitrary-value utilities are generated and the compiled CSS stays static.

Radius

One base variable derives the whole scale by offset, so changing a single value re-scales every radius utility:

@theme inline {
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
}

Box radius accepts the compiled keys: "none", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl".

Class discovery

Tailwind v4 scans source files to know which utilities exist. The token-generated classes are composed at build time inside lib/tokens.ts, so make sure your content configuration sees that file:

@source "../**/*.{ts,tsx}";

If your scanner cannot see the module (for example, you consume a built dist), tokens.ts also exports _safelist: a space-joined string of every generated utility for @source inline(...).

Dark mode

All color tokens are CSS variables. To support dark mode, re-declare them under a .dark class (and Tailwind's dark variant of your choice) — borders and overlays usually work best as alpha whites in dark. Wiring a theme switcher is up to your application; the registry ships tokens, not a provider.