Documentation

How to Add a Theme

Learn how to create and add a new theme to your Astro Theme Switcher project. Follow these simple steps to extend the theme system.

Overview

The theme system uses semantic design tokens defined in TypeScript. Each theme consists of three files:

  • tokens.ts - Defines all design tokens (colors, typography, spacing, etc.) - You edit this
  • meta.json - Theme metadata (name, description, version) - You edit this
  • theme.css - Generated CSS custom properties (auto-generated from tokens via npm run generate-themes) - Auto-generated, don't edit

Themes are automatically registered in the theme system and appear in the theme switcher once added.

Step-by-Step Guide

1

Create Theme Directory

Create a new directory in src/themes/ with your theme name (e.g., red, pink).

src/themes/
  ├── blue/
  ├── green/
  ├── red/        ← Your new theme
  │   ├── tokens.ts
  │   ├── meta.json
  │   └── theme.css
2

Define Design Tokens

Create tokens.ts with your theme's design tokens. Use semantic names (primary, surface, text.primary) rather than raw color values.

import type { DesignTokens } from '../types';

export const tokens: DesignTokens = {
  color: {
    primary: '#ef4444',
    primaryForeground: '#ffffff',
    secondary: '#fee2e2',
    secondaryForeground: '#7f1d1d',
    accent: '#fecaca',
    accentForeground: '#7f1d1d',
    background: '#fef2f2',
    surface: '#fee2e2',
    surfaceElevated: '#ffffff',
    text: {
      primary: '#7f1d1d',
      secondary: '#991b1b',
      muted: '#dc2626',
      inverse: '#ffffff',
    },
    border: '#fecaca',
    borderMuted: '#fee2e2',
    borderStrong: '#f87171',
    success: '#10b981',
    successForeground: '#ffffff',
    warning: '#f59e0b',
    warningForeground: '#ffffff',
    error: '#ef4444',
    errorForeground: '#ffffff',
    info: '#3b82f6',
    infoForeground: '#ffffff',
    hover: 'rgba(239, 68, 68, 0.1)',
    active: 'rgba(239, 68, 68, 0.2)',
    focus: '#ef4444',
  },
  typography: {
    fontFamily: {
      sans: 'ui-sans-serif, system-ui, ...',
      serif: 'ui-serif, Georgia, ...',
      mono: 'ui-monospace, SFMono-Regular, ...',
    },
    // ... fontSize, fontWeight, etc.
  },
  radius: {
    sm: '0.125rem',
    md: '0.375rem',
    // ... more radius values
  },
  shadow: {
    1: '0 1px 2px 0 rgb(239 68 68 / 0.1)',
    // ... more shadow values
  },
  motion: {
    duration: {
      fast: '150ms',
      normal: '200ms',
      slow: '300ms',
    },
    easing: {
      default: 'cubic-bezier(0.4, 0, 0.2, 1)',
      // ... more easing values
    },
  },
};

💡 Tip: Copy an existing theme's tokens.ts file and modify the color values to match your theme.

3

Add Theme Metadata

Create meta.json with your theme's information.

{
  "id": "red",
  "name": "Red",
  "description": "Bold red color scheme",
  "version": "1.0.0",
  "premium": false,
  "tags": ["red", "bold", "energetic"]
}
4

Generate Theme CSS

The theme.css file is automatically generated from your tokens. You don't need to write CSS manually!

npm run generate-themes

This command will:

  • Read your tokens.ts file
  • Generate theme.css with CSS custom properties
  • Automatically create both light and dark mode variants
/* Red Theme - Light Mode */
[data-theme="red"][data-mode="light"] {
  --token-color-primary: #ef4444;
  --token-color-primary-foreground: #ffffff;
  --token-color-background: #fef2f2;
  --token-color-surface: #fee2e2;
  --token-color-text-primary: #7f1d1d;
  /* ... more tokens ... */
}

/* Red Theme - Dark Mode */
[data-theme="red"][data-mode="dark"] {
  --token-color-primary: #f87171;
  --token-color-primary-foreground: #ffffff;
  --token-color-background: #7f1d1d;
  --token-color-surface: #991b1b;
  --token-color-text-primary: #fee2e2;
  /* ... more tokens ... */
}

💡 Note: The theme.css file is auto-generated. Always edit tokens.ts and run npm run generate-themes to regenerate the CSS.

5

Register the Theme

Add your theme to the theme registry in src/themes/index.ts.

// Import your theme
import { tokens as redTokens } from './red/tokens';
import redMeta from './red/meta.json';

// Add to themes array
export const themes: Theme[] = [
  // ... existing themes
  {
    meta: redMeta as ThemeMeta,
    tokens: redTokens,
  },
];
6

Import Theme CSS

Add your theme's CSS import to src/themes/themes.css.

@import './light/theme.css';
@import './dark/theme.css';
@import './blue/theme.css';
/* ... other themes ... */
@import './red/theme.css';  ← Add your theme

Best Practices

Use Semantic Tokens

Always use semantic token names (primary, surface, text.primary) rather than raw color values. This ensures your theme works with all components automatically.

Ensure Contrast

Make sure text colors have sufficient contrast against their backgrounds. Use WCAG AA standards (4.5:1 for normal text, 3:1 for large text).

Test Both Modes

Each color theme should have distinct light and dark mode variants. Test both modes to ensure readability and visual appeal.

Follow Naming Conventions

Use lowercase, kebab-case for theme IDs (e.g., "red", "dark-blue"). Keep names descriptive and consistent with existing themes.

Ready to Create Your Theme?

Start by copying an existing theme and customizing it to match your brand.