Docs / Theme System Architecture

Theme System Architecture

Deep dive into the two-layer variable system that powers theme and dark/light mode switching.

The kit uses a two-layer variable architecture that separates brand identity from light/dark mode. This separation enables independent control over both axes—switch themes and modes without duplicating components, blocks, or pages.

Variable Collections

The system uses two separate Figma variable collections working together:

CollectionLayerPurpose
ThemeBrand LayerDefines semantic tokens using Tailwind primitives and Shadcn CSS variable names
Theme ModeLight/Dark LayerRoutes components to the correct light or dark values from the active theme

Theme Collection (Brand Layer)

The Theme collection defines design tokens using:

  • Hex values
  • Tailwind primitive variables
  • Standard Shadcn/Tweakcn CSS variable names

Theme Columns

The collection includes multiple theme columns:

ColumnDescription
DefaultStandard Shadcn variables
AmberTweakcn-style amber theme

Each column defines the full semantic token set with both light and dark variants:

  • background / background-dark
  • foreground / foreground-dark
  • primary / primary-dark
  • primary-foreground / primary-foreground-dark
  • secondary / secondary-dark
  • muted / muted-dark
  • accent / accent-dark
  • destructive / destructive-dark
  • border / border-dark
  • ring / ring-dark

These match real Shadcn CSS variable names exactly. The -dark suffix tokens are required to interface with the Theme Mode collection for light/dark switching.

Token Examples

TokenDefaultAmber
primaryneutral/900amber/400
primary-darkneutral/50amber/300
backgroundwhiteneutral/50
background-darkneutral/950neutral/900

This layer controls brand identity. Switching from Default → Amber updates the entire semantic color system for both light and dark modes.

Theme Mode Collection (Light/Dark Layer)

This is the key architectural decision that enables simultaneous theme and mode switching.

How It Works

Instead of components directly referencing primary, they reference:

Theme Mode → primary

Inside Theme Mode:

  • Light mode → maps to Theme.primary
  • Dark mode → maps to Theme.primary-dark

Theme Mode acts as a routing layer between components and theme values.

Why Two Layers?

Without this mapping layer, you could:

  • Switch themes, OR
  • Switch light/dark

But not both cleanly at scale.

With this system:

Changing Theme Switch column in the Theme collection → All semantic tokens update

Changing Mode Switch mode in the Theme Mode collection → Pulls the correct light or dark variant from the active theme

Both can be changed independently.

Data Flow

The architecture follows this hierarchy:

Tailwind Primitives / Hex

Theme Collection (Brand Values)

Theme Mode Collection (Light/Dark Mapping)

Components + 500 Pro Blocks

Components never reference:

  • Hex values
  • Tailwind primitive tokens
  • Raw theme variables

They reference Theme Mode variables only.

That abstraction is what makes global switching possible.

Adding a New Theme

To add a new theme:

  1. Add a new column in the Theme collection
  2. Define the semantic tokens
  3. Done
  4. Click on any page and in the top right use the variable mode to see your new theme and apply it