Skip to main content
Reference

Theme system standard

43 oklch color themes via tweakcn. Theme switching, CSS variable architecture, dark mode.

Theme system standard

Purpose: Defines the multi-theme architecture that ships with every prototype, covering 43 color themes with light/dark variants, CSS variable structure, and font loading.

Every prototype ships with professional theming. 43 themes transform the entire experience.

Principle

Theme selection transforms the full visual experience -- background, cards, borders, text, accents, fonts, and border radius. A theme that only changes the primary color is not a real theme; it's a color accent.

What's included

The prototype scaffold ships with 43 color themes (1 default + 42 from tweakcn), each with light and dark variants:

# Theme # Theme # Theme
1 Default 16 Quantum Rose 31 Midnight Bloom
2 Modern Minimal 17 Nature 32 Candyland
3 Violet Bloom 18 Bold Tech 33 Northern Lights
4 T3 Chat 19 Elegant Luxury 34 Vintage Paper
5 Twitter 20 Amber Minimal 35 Sunset Horizon
6 Mocha Mousse 21 Supabase 36 Starry Night
7 Bubblegum 22 Neo Brutalism 37 Claude
8 Amethyst Haze 23 Solar Dusk 38 Vercel
9 Notebook 24 Claymorphism 39 Darkmatter
10 Doom 64 25 Cyberpunk 40 Mono
11 Catppuccin 26 Pastel Dreams 41 Soft Pop
12 Graphite 27 Clean Slate 42 Sage Garden
13 Perpetuity 28 Caffeine
14 Kodama Grove 29 Ocean Breeze
15 Cosmic Night 30 Retro Arcade

Total combinations: 86 (43 themes x 2 modes).

Attribution

Theme presets adapted from tweakcn by @jnsahaj, licensed under Apache 2.0.

How it works

  • Light/dark modenext-themes manages the dark class on <html>
  • Color themes — Runtime CSS custom properties applied via document.documentElement.style
  • Independent and composable — Selecting a color theme + toggling dark mode work together seamlessly
  • Persisted via localStorage — Key: theme-color
  • Fonts load lazily — Google Fonts CDN links are injected only when a theme using them is selected

Architecture

┌─────────────────────────────────────────────┐
│ ThemeProvider (layout.tsx)                   │
│  ├─ NextThemesProvider  (light/dark/system)  │
│  └─ ColorThemeProvider  (43 color themes)    │
│      ├─ reads: lib/themes/presets.ts         │
│      ├─ calls: lib/themes/apply-theme.ts     │
│      └─ calls: lib/themes/fonts.ts           │
└─────────────────────────────────────────────┘
File Purpose
lib/themes/types.ts TypeScript interfaces for theme system
lib/themes/presets.ts All 43 theme definitions (colors, radius, fonts)
lib/themes/apply-theme.ts Runtime CSS variable application via document.documentElement.style
lib/themes/fonts.ts Lazy Google Fonts CDN loading
components/theme-provider.tsx Combined provider: NextThemesProvider + ColorThemeProvider
components/theme-picker.tsx Theme selection UI (scrollable list, search, swatches)
components/mode-toggle.tsx Light/dark/system toggle (unchanged)
app/globals.css Default :root / .dark variable definitions

Color format

Theme presets use hex color values (the format used by tweakcn). The default :root / .dark variables in globals.css use oklch (shadcn defaults). When a color theme is active, the hex values override the oklch defaults at runtime.

CSS variables

Each theme defines 32 CSS custom properties:

  • --background, --foreground — Page background and text
  • --card, --card-foreground — Card surfaces
  • --popover, --popover-foreground — Dropdown/popover surfaces
  • --primary, --primary-foreground — Primary actions
  • --secondary, --secondary-foreground — Secondary surfaces
  • --muted, --muted-foreground — Muted/subtle elements
  • --accent, --accent-foreground — Accent highlights
  • --destructive, --destructive-foreground — Destructive/danger actions
  • --border, --input, --ring — Borders, inputs, focus rings
  • --chart-1 through --chart-5 — Chart colors
  • --sidebar, --sidebar-foreground, etc. — Sidebar-specific colors
  • --radius — Border radius

Font system

Some themes include custom Google Fonts (sans, serif, mono). Fonts are loaded lazily -- the <link> tag is injected into <head> only when a theme that uses them is selected. Font families already loaded are tracked to prevent duplicate requests.

Prototype phase checklist

  • Does the feature render correctly in the Default theme?
  • Spot-check at least 3 other themes (e.g., Neo Brutalism, Ocean Breeze, Claude)
  • Does it work in both light and dark modes?
  • Are all interactive elements visible and accessible in all theme/mode combinations?
  • Do custom colors (if any) meet WCAG AA contrast in all themes?
  • Is the theme picker visible and functional?

Adding custom brand themes

  1. Add a new ThemePreset object — In lib/themes/presets.ts
  2. Define all 32 CSS variable values — For both light and dark variants
  3. Assign custom fonts — Optionally via the fonts field
  4. Add the new preset — To the themePresets array export
  5. Test in both modes — Light and dark
  6. Verify contrast ratios — WCAG AA compliance

Example

const my_brand: ThemePreset = {
  id: "my-brand",
  label: "My Brand",
  radius: "0.5rem",
  fonts: {
    sans: "Inter, sans-serif",
  },
  light: {
    background: "#ffffff",
    foreground: "#1a1a1a",
    primary: "#3b82f6",
    // ... all 32 variables
  },
  dark: {
    background: "#0a0a0a",
    foreground: "#fafafa",
    primary: "#60a5fa",
    // ... all 32 variables
  },
}

Theme System Standard -- March 2026

Search Framework Explorer

Search agents, skills, and standards