Colors
Two layers. Primitives are the raw palette — thirteen scales from 50 to 950. Semantic tokens give those colors a job so every surface, text and border resolves through a token. Click any swatch or chip to copy.
npx shadcn@latest add http://localhost:5178/registry/tokens.json
How the system works
The written model behind the swatches above. Read this to know which token to reach for and why.
Two-tier architecture
Primitive is what the value is (gray/950). Semantic is what it means / where it's used (text.primary). Components consume the semantic token, never the raw primitive — so a primitive can change (text.primary → gray/900) without touching a single component.
Naming dimensions
A semantic name can describe up to four things. Read a name as context.role — sometimes with emphasis or state.
text · icon · background · border · actioninformation · warning · negative · positiveprimary · secondary · muted · disabledhover · clicked · disabledChoosing a token
Don't start with “which shade?” Start with “what is this color doing?”
| Designing… | Ask… | Reach for |
|---|---|---|
| Text | How important is this content? | text.* |
| Icon | How important is this icon? | icon.* |
| Surface | What kind of surface is this? | background.* |
| Interactive control | What action / state is occurring? | action.* |
| Boundary | What does the boundary separate? | border.* |
| Success / warning / error / info | What is it communicating? | positive · warning · negative · information |
When to add a new token
- It represents a real UI role.
- It communicates meaning, emphasis, purpose, or state.
- Its purpose can be explained without a hex value.
- The name stays meaningful if the primitive changes.
- The interface actually needs it.
- You're defining a role — not reproducing the palette.
Avoid minting information/50…950 just because those shades exist. Prefer information.text, information.icon, information.border — purpose-driven, not scale-driven.
Primitive vs semantic
| Primitive — what value is this? | Semantic — why am I using it here? |
|---|---|
gray/950 | text.primary |
blue/500 | information.icon |
green/200 | positive.border |
sky/600 | action.primary |
white | text.inverse |
Registry principle
In the token registry the semantic layer stays independent of the primitive layer. Dots flatten to CSS variables — text.primary becomes --text-primary, warning.border-strong becomes --warning-border-strong. A component uses var(--text-primary), so the primitive underneath can evolve without a component-by-component rewrite.
Typography
One unified scale in Inter — six headings and four paragraph sizes, with five weights. Each value shows as size / line-height. Sizes come from the Figma variables; the presets derive from the tokens.
Quick reference
A short do / don't for applying the type scale.
- Use the presets —
.type-h1….type-h6,.type-paragraph-lg/md/sm/smx. - Pick a level by role (heading rank, body copy), then set weight with
.fw-*. - Keep to the one unified scale — the same sizes across web and mobile.
- Pair size with its bundled line-height; let the token carry both.
- Invent arbitrary font sizes (
text-[15px]) outside the scale. - Use SMX or the smallest sizes for standard body copy.
- Hand-set line-heights that drift off the scale's pairing.
- Skip heading ranks for visual weight — reach for a weight utility instead.
Foundation
The primitive scales the whole system builds on — spacing and elevation today, with corner radius and more to follow. Every value is sourced from the tokens, never invented.
Spacing
Uses Tailwind v4's default base unit --spacing: 0.25rem (4px) — not overridden. Every p-*, m-*, gap-*, and space-* utility is a multiple of that base. The steps below are the ones actually used across the system.
Shadow
Elevation and inset effects that communicate depth and interaction — black with controlled opacity, not a gray palette.
Button
Buttons allow users to perform an action or make a decision.
design system
Design system documentation — the pages from Notion, rendered here in the app (Notion can't be embedded, so this mirrors its structure and links out).