Skip to main content
Skip to content

Last updated on 4 June 2026

Design Tokens

The visual system is driven by semantic CSS custom properties rather than hardcoded component colours. This keeps each template edition easy to rebrand and lets light/dark mode cascade through the whole app.

Source Of Truth

  • src/app/globals.css -- Tailwind CSS v4 imports, @theme inline mappings, light tokens, dark tokens, focus styles, layout helpers, and global component polish.
  • src/app/layout.tsx -- font loading when the template uses next/font.
  • src/themes/* -- edition-level overrides when the template ships a theme file. Some editions keep all preset overrides directly in globals.css instead.
  • src/lib/site-config.ts -- product name, brand name, legal identity, and any theme accent fields exposed by the local template.

For most buyer rebrands, edit src/app/globals.css first. Use src/lib/site-config.ts for product identity and email colours, and check src/lib/email/index.ts to confirm which theme accent key the mailer reads in your template edition.

Token Pattern

Tokens are named by role, not by raw colour:

css
:root {
  --background: oklch(...);
  --foreground: oklch(...);
  --surface: oklch(...);
  --border: oklch(...);
  --accent: oklch(...);
}

[data-theme='dark'] {
  --background: oklch(...);
  --foreground: oklch(...);
}

Components then consume semantic Tailwind utilities such as bg-background, text-foreground, border-border, and bg-accent. Avoid adding one-off hex, RGB, or OKLCH values inside JSX.

Light And Dark Mode

Dark mode is scoped through the data-theme="dark" attribute. The theme script and theme provider set that attribute before the app paints so users do not see a flash between modes.

When changing the palette:

  1. Update the light tokens in :root.
  2. Update the dark tokens in [data-theme='dark'].
  3. Check focus rings, selected states, disabled states, charts, and tables.
  4. Test legal pages and email preview pages as well as dashboard pages.

Fonts

Font roles are mapped through CSS variables:

  • --font-sans
  • --font-display
  • --font-mono

Font loading is template-specific. Some editions load fonts in src/app/layout.tsx with next/font; others rely on CSS fallback stacks. The font roles are mapped in src/app/globals.css, usually through --font-display-family and related variables. Keep fallback stacks in place so the UI remains stable if a custom font fails to load.

Focus And Accessibility Tokens

Global focus styles are centralised in src/app/globals.css. Do not repeat focus utility classes on every input unless a component genuinely needs a custom focus treatment.

The default pattern uses:

  • :focus-visible for keyboard focus on links, buttons, and custom controls
  • input/select/textarea focus styles for form fields
  • semantic accent tokens so focus indicators match the brand palette

Email Accent

Transactional emails cannot rely on OKLCH or CSS variables in every email client. Use an email-safe hex or RGB colour for the accent field that your template's mailer reads.

Check both:

  • src/lib/site-config.ts
  • src/lib/email/index.ts

Most editions read SITE_CONFIG.theme.accent; some editions expose a dedicated email-safe field. Do not add a new theme key unless the email helper already reads it.

Rebrand Checklist

  1. Replace product and legal identity in src/lib/site-config.ts.
  2. Update semantic colour tokens in src/app/globals.css.
  3. Update font loading in src/app/layout.tsx when your template uses next/font, then map the font role in src/app/globals.css.
  4. Search for any remaining hardcoded colour classes in src/.
  5. Test light mode, dark mode, mobile, dashboard tables, forms, legal pages, and transactional email previews.