Overview
This guide walks through customizing the design token system for a client site. The theme is built on a three-layer token architecture that separates raw values from their semantic meaning and from Tailwind’s utility layer. Understanding these layers is the key to efficient rebranding.
Who this is for
- Implementors rebranding the theme for a client site — colors, typography, spacing, and dark mode
Token layers
The theme uses a three-layer token architecture: primitives (--pt-*) → semantic (--st-*) → Tailwind bridge (@theme). Components consume semantic tokens only. For the full model, layer rules, and when to create semantic tokens, see Design Tokens — Three-Layer Model (DOC-00004).
Site-level theme overrides
The site customization point is src/site/styles/. Files here shadow (override) their core counterparts in src/core/styles/:
| Site file | Overrides |
|---|---|
src/site/styles/primitives.css | Color swatches, raw scale values |
src/site/styles/semantic.css | Token-to-primitive mappings |
src/site/styles/light.css | Light mode token values |
src/site/styles/dark.css | Dark mode token values |
src/site/config/fonts.config.ts | Fonts API configuration |
src/site/styles/base.css | Base element styles |
src/site/styles/components.css | Component-level style overrides |
src/site/styles/bridge.css | Tailwind utility registrations |
src/site/styles/starwind-bridge.css | Optional Starwind bridge activation and Starwind-specific aliases |
src/site/styles/fluid-tokens.css | Generated fluid token output |
To override a token, redeclare it in the corresponding site file. The site value takes precedence over the core default.
Customizing colors
Brand colors flow through two files:
-
Define the palette in
src/site/styles/primitives.css. Add or modify--pt-color-*custom properties with your brand swatches. -
Map to semantic roles in
src/site/styles/semantic.css. Point semantic tokens like--st-color-brand-primaryat your new primitives.
Because semantic tokens reference primitives, changing a primitive value cascades to every component that uses the corresponding semantic token. This is the intended workflow — change at the primitive level, and the entire theme updates.
Example
/* src/site/styles/primitives.css */
:root {
--pt-color-blue-600: #2563eb;
}
/* src/site/styles/semantic.css */
:root {
--st-color-brand-primary: var(--pt-color-blue-600);
}
Customizing typography
Typography tokens follow the same primitive-to-semantic pattern:
- Font families — Core provides default fonts in
src/core/config/fonts.config.ts. Editsrc/site/config/fonts.config.tsto replace the defaults with a customFontEntry[]array. The Astro Fonts API generates@font-facerules and metric-adjusted fallbacks automatically. Override--pt-font-*or--st-font-*tokens ifcssVariablenames change. - Font sizes — Override
--pt-text-*primitives for raw sizes, or remap--st-text-*semantic tokens for role-based sizing. - Line heights — Adjust
--pt-leading-*or--st-leading-*tokens.
Customizing spacing and radius
- Spacing scale — The spacing scale uses
--pt-space-*primitives mapped to--st-space-*semantic tokens. Override either layer in the corresponding site file. - Border radius — Radius tokens (
--pt-radius-*/--st-radius-*) control corner rounding across components. Changing the radius primitives updates buttons, cards, inputs, and other rounded elements consistently.
Fluid token system
The project includes a fluid token generator that produces responsive clamp() values for typography and spacing. These tokens scale smoothly between a minimum and maximum viewport width.
Configuration files
- Core defaults:
src/core/config/fluid-tokens.config.ts - Site overrides:
src/site/config/fluid-tokens.config.ts
The site config file overrides or extends the core defaults.
Workflow
- Edit the fluid token config (typically the site override).
- Run
npm run generate:tokensto regenerate the CSS output files (src/core/styles/fluid-tokens.cssandsrc/site/styles/fluid-tokens.css). - Verify the output with
npm run dev.
Drift detection
Run npm run generate:tokens:check to verify that the generated CSS matches the current config. This check runs automatically as part of npm run validate, so any drift is caught before commits.
Dark mode and theme modes
The token system defines both light and dark mode values:
- Light mode tokens —
src/core/styles/light.css(core) andsrc/site/styles/light.css(site overrides) - Dark mode tokens —
src/core/styles/dark.css(core) andsrc/site/styles/dark.css(site overrides)
Each mode file re-declares semantic tokens with mode-appropriate values. When switching between modes, these declarations swap which primitives the semantic tokens point to.
When dark mode is active, the <html> element carries both data-theme="dark" and the .dark class. The project’s own token system uses [data-theme="dark"] selectors. The .dark class is set alongside data-theme for compatibility with external Tailwind ecosystem libraries (Starwind, Flowbite, shadcn/ui, DaisyUI) that use .dark as their dark mode hook. External libraries that define @custom-variant dark (&:where(.dark, .dark *)) will activate their dark styles automatically.
To customize dark mode, override the relevant tokens in src/site/styles/dark.css. Ensure adequate contrast ratios (WCAG 2.2 AA) in both modes.
Testing token changes
After modifying tokens:
- Preview locally — Run
npm run devand inspect affected components. Check both light and dark modes. - Visual verification — Visit the showcase-tokens page at
/theme-docs/showcase/showcase-tokens/to see all tokens rendered in one place. This catches unintended cascading effects. - Run validation — Execute
npm run validateto ensure token changes pass lint checks, drift detection, and the full build. - Contrast checking — Verify that color token changes maintain WCAG 2.2 AA contrast ratios, especially for text-on-surface and interactive element combinations.