Reference

Theme Structure

A detailed look at how the tweakcn registry works and what gets installed when you run the CLI command.

Registry Overview

tweakcn uses the official shadcn/ui registry format. This means you install themes using the same shadcn add command you use for components.

Available Registry Items

nextjs/theme-systemComplete theme system for Next.js
vite/theme-systemComplete theme system for Vite + React
astro/theme-systemComplete theme system for Astro
remix/theme-systemComplete theme system for Remix
theme-[name]Individual theme CSS (38 themes available)

Files Created by CLI

When you install the theme system, these files are created in your project:

Project Structure (Next.js)text
your-project/
├── components/
│ ├── providers/
│ │ └── theme-provider.tsx # ThemeProvider component
│ └── theme-switcher.tsx # ThemeSwitcher dropdown
├── lib/
│ └── themes-config.ts # Theme configuration & exports
└── styles/
└── themes/
├── index.css # Imports all theme CSS
├── default.css # Default theme
├── catppuccin.css # Catppuccin theme
├── claude.css # Claude theme
├── vercel.css # Vercel theme
└── ... (38 theme files)

themes-config.ts

Theme metadata, exports for useTheme, and helper utilities

theme-provider.tsx

Pre-configured next-themes provider with all themes

theme-switcher.tsx

Ready-to-use dropdown for theme switching

styles/themes/*.css

38 theme CSS files with light and dark variants

themes-config.ts

The central configuration file that defines all theme metadata and exports utilities for working with themes:

lib/themes-config.tstsx
1// Theme configuration interface
2export interface ThemeConfig {
3 name: string; // Theme identifier (e.g., "catppuccin")
4 title: string; // Display name (e.g., "Catppuccin")
5 primaryLight: string; // Primary color for light mode (OKLCH)
6 primaryDark: string; // Primary color for dark mode (OKLCH)
7 fontSans: string; // Font family
8}
9
10// All 38 themes with metadata
11export const themes: ThemeConfig[] = [
12 {
13 name: "default",
14 title: "Default",
15 primaryLight: "oklch(0.2050 0 0)",
16 primaryDark: "oklch(0.9220 0 0)",
17 fontSans: "ui-sans-serif, system-ui, sans-serif",
18 },
19 {
20 name: "catppuccin",
21 title: "Catppuccin",
22 primaryLight: "oklch(0.55 0.25 297.02)",
23 primaryDark: "oklch(0.79 0.12 304.77)",
24 fontSans: "Montserrat, sans-serif",
25 },
26 // ... 36 more themes
27];
28
29// Sorted alphabetically (default first)
30export const sortedThemes = [
31 themes[0],
32 ...themes.slice(1).sort((a, b) => a.title.localeCompare(b.title)),
33];
34
35// Theme names array
36export const themeNames = themes.map((t) => t.name);
37
38// All theme values for next-themes: ["default-light", "default-dark", ...]
39export const allThemeValues = themes.flatMap((t) => [
40 `${t.name}-light`,
41 `${t.name}-dark`,
42]);
43
44// Default theme
45export const DEFAULT_THEME = "default-dark";

ThemeProvider

A pre-configured provider using next-themes with all themes registered:

components/providers/theme-provider.tsxtsx
1"use client";
2
3import { ThemeProvider as NextThemesProvider } from "next-themes";
4import { ReactNode } from "react";
5import { allThemeValues, DEFAULT_THEME } from "@/lib/themes-config";
6
7export function ThemeProvider({ children }: { children: ReactNode }) {
8 return (
9 <NextThemesProvider
10 attribute="data-theme" // Uses data-theme attribute
11 themes={allThemeValues} // All 76 theme values (38 × 2)
12 defaultTheme={DEFAULT_THEME} // "default-dark"
13 enableSystem={false}
14 disableTransitionOnChange
15 >
16 {children}
17 </NextThemesProvider>
18 );
19}

Key Configuration

  • attribute="data-theme" - Themes are applied via data-theme attribute, not class
  • themes={allThemeValues} - All 76 theme values (38 themes × 2 modes)
  • enableSystem={false} - System preference disabled (manual control)

ThemeSwitcher Component

A complete dropdown component for switching themes:

components/theme-switcher.tsx (simplified)tsx
1"use client";
2
3import { useTheme } from "next-themes";
4import { sortedThemes, themes } from "@/lib/themes-config";
5
6// Parse theme string like "catppuccin-dark" into parts
7function parseTheme(theme: string | undefined) {
8 if (!theme) return { colorTheme: "default", mode: "dark" };
9 if (theme.endsWith("-dark")) {
10 return { colorTheme: theme.replace("-dark", ""), mode: "dark" };
11 }
12 if (theme.endsWith("-light")) {
13 return { colorTheme: theme.replace("-light", ""), mode: "light" };
14 }
15 return { colorTheme: "default", mode: "dark" };
16}
17
18export function ThemeSwitcher() {
19 const { theme, setTheme } = useTheme();
20 const { colorTheme, mode } = parseTheme(theme);
21
22 // Change color theme, keep current mode
23 const setColorTheme = (name: string) => {
24 setTheme(`${name}-${mode}`);
25 };
26
27 // Change mode, keep current color theme
28 const setMode = (newMode: "light" | "dark") => {
29 setTheme(`${colorTheme}-${newMode}`);
30 };
31
32 // ... dropdown UI with sortedThemes.map(...)
33}

Theme CSS Structure

Each theme CSS file defines variables for both light and dark modes using data-theme selectors:

styles/themes/catppuccin.csscss
1/* Catppuccin Theme - Auto-generated from tweakcn */
2
3/* Light mode */
4[data-theme="catppuccin-light"] {
5 /* Base colors */
6 --background: oklch(0.96 0.01 264.53);
7 --foreground: oklch(0.44 0.04 279.33);
8
9 /* Component colors */
10 --card: oklch(1 0 0);
11 --card-foreground: oklch(0.44 0.04 279.33);
12 --popover: oklch(0.86 0.01 268.48);
13 --popover-foreground: oklch(0.44 0.04 279.33);
14
15 /* Semantic colors */
16 --primary: oklch(0.55 0.25 297.02);
17 --primary-foreground: oklch(1 0 0);
18 --secondary: oklch(0.86 0.01 268.48);
19 --secondary-foreground: oklch(0.44 0.04 279.33);
20 --muted: oklch(0.91 0.01 264.51);
21 --muted-foreground: oklch(0.55 0.03 279.08);
22 --accent: oklch(0.68 0.14 235.38);
23 --accent-foreground: oklch(1 0 0);
24 --destructive: oklch(0.55 0.22 19.81);
25 --destructive-foreground: oklch(1 0 0);
26
27 /* UI colors */
28 --border: oklch(0.81 0.02 271.2);
29 --input: oklch(0.86 0.01 268.48);
30 --ring: oklch(0.55 0.25 297.02);
31
32 /* Chart colors */
33 --chart-1: oklch(0.55 0.25 297.02);
34 --chart-2: oklch(0.68 0.14 235.38);
35 --chart-3: oklch(0.63 0.18 140.44);
36 --chart-4: oklch(0.69 0.2 42.43);
37 --chart-5: oklch(0.71 0.1 33.1);
38
39 /* Sidebar colors */
40 --sidebar: oklch(0.93 0.01 264.52);
41 --sidebar-foreground: oklch(0.44 0.04 279.33);
42 --sidebar-primary: oklch(0.55 0.25 297.02);
43 --sidebar-primary-foreground: oklch(1 0 0);
44 --sidebar-accent: oklch(0.68 0.14 235.38);
45 --sidebar-accent-foreground: oklch(1 0 0);
46 --sidebar-border: oklch(0.81 0.02 271.2);
47 --sidebar-ring: oklch(0.55 0.25 297.02);
48
49 /* Typography */
50 --font-sans: Montserrat, sans-serif;
51 --font-serif: Georgia, serif;
52 --font-mono: Fira Code, monospace;
53
54 /* Spacing & radius */
55 --radius: 0.35rem;
56 --spacing: 0.25rem;
57
58 /* Shadows */
59 --shadow-sm: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), ...;
60 --shadow-md: ...;
61 --shadow-lg: ...;
62}
63
64/* Dark mode */
65[data-theme="catppuccin-dark"] {
66 --background: oklch(0.22 0.03 284.06);
67 --foreground: oklch(0.88 0.04 272.28);
68 /* ... all dark mode variables */
69}

Theme Index File

The index.css file imports all theme CSS files. This is what you import in your globals.css:

styles/themes/index.csscss
1/* Theme imports */
2@import "./default.css";
3@import "./catppuccin.css";
4@import "./claude.css";
5@import "./vercel.css";
6@import "./cyberpunk.css";
7@import "./mocha-mousse.css";
8/* ... all 38 themes */
app/globals.csscss
1@import "tailwindcss";
2
3/* Import all themes */
4@import "../styles/themes/index.css";
5
6@layer base {
7 * {
8 @apply border-border;
9 }
10 body {
11 @apply bg-background text-foreground;
12 }
13}

CSS Variable Reference

All CSS variables defined in each theme:

VariableUsage
--backgroundPage/app background color
--foregroundPrimary text color
--cardCard component backgrounds
--popoverDropdown, popover backgrounds
--primaryPrimary brand color, buttons, links
--secondarySecondary elements, less emphasis
--mutedSubdued backgrounds, disabled states
--accentHighlights, hover states
--destructiveError states, delete actions
--borderBorder color for all elements
--inputInput field backgrounds/borders
--ringFocus ring color
--chart-1 to --chart-5Chart/graph colors
--sidebar-*Sidebar-specific colors
--font-sansSans-serif font stack
--font-serifSerif font stack
--font-monoMonospace font stack
--radiusBase border radius
--shadow-*Shadow scale (2xs, xs, sm, md, lg, xl, 2xl)

Individual Theme Installation

You can also install individual themes without the full system:

$ pnpm dlx shadcn@latest add pnpm dlx shadcn@latest add https://tweakcn-picker.vercel.app/r/theme-catppuccin.json