Getting Started
The Cascade
How BDS tokens layer from Figma foundations to client themes.
BDS uses a three-layer cascade. Each layer is a single CSS file imported in order.
The three layers
- Foundations (
figma-tokens.css) — auto-generated from Figma variables. Never hand-edit. - Gap-fills (
gap-fills.css) — interaction-state tokens (hover, pressed) that haven't graduated to Figma yet. - Client theme (
theme-{client}.css) — per-project overrides for brand color, typography, atmosphere.
Never write raw var() strings inline. Always go through @/lib/tokens and @/lib/styles. The cascade is a contract — bypassing it leaks brand drift into components.
Why this order
Foundations define the full token vocabulary. Gap-fills add what Figma can't yet express. Client themes override semantic tokens (e.g. --text-brand) without touching the underlying scales (--color-orange-500). A component that reads --text-brand automatically picks up whichever client is active.
What each layer can change
| Layer | Can override |
|---|---|
| Foundations | Nothing — it's the source |
| Gap-fills | Interaction states only |
| Client theme | Semantic tokens (text, background, border, brand) |
| Atmospheres | Mood layer (warm-soft, editorial-luxury, etc.) — applied as a class |
Where this is enforced
The lint-tokens script (npm run lint-tokens) catches:
- Hex values in component CSS
var()references to tokens that don't exist- Tokens used outside their semantic category (e.g.
--text-*on abackground-color)
Run it locally before pushing; CI runs it on every PR.