Help us improve
Share bugs, ideas, or general feedback.
From source-design
Generate a complete color and typography theme as CSS custom properties. Outputs a ready-to-use theme file with light/dark mode, semantic tokens, and Tailwind config. Use when starting a new project or creating a theme system.
npx claudepluginhub liamfuller07/source-design-pluginHow this skill is triggered — by the user, by Claude, or both
Slash command
/source-design:design-themeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a complete, production-ready theme system as CSS custom properties with Tailwind integration.
Configures Tailwind CSS @theme for advanced design systems with semantic colors, brand scales, typography scales, line heights, and spacing tokens.
Designs token-based theming systems for multi-brand design systems supporting light/dark/high-contrast modes, density variants, and runtime switching.
Bootstraps design systems by generating design tokens, Tailwind configs, CSS variables, typography scales, spacing systems, and component inventories from project context.
Share bugs, ideas, or general feedback.
Generate a complete, production-ready theme system as CSS custom properties with Tailwind integration.
Ask or determine:
Create systematic 10-step scales using OKLCH for perceptual uniformity:
:root {
/* === PRIMITIVES === */
/* Neutral (warm gray example) */
--gray-50: #fafaf9;
--gray-100: #f5f5f4;
--gray-200: #e7e5e4;
--gray-300: #d6d3d1;
--gray-400: #a8a29e;
--gray-500: #78716c;
--gray-600: #57534e;
--gray-700: #44403c;
--gray-800: #292524;
--gray-900: #1c1917;
--gray-950: #0c0a09;
/* Primary (generate from brand color) */
--primary-50: ...;
--primary-100: ...;
/* ... through 950 */
/* Semantic */
--green-500: #10B981;
--red-500: #DC2626;
--amber-500: #F59E0B;
--blue-500: #3b82f6;
/* === SEMANTIC TOKENS === */
/* Surfaces */
--bg-base: var(--gray-50);
--bg-elevated: #ffffff;
--bg-recessed: var(--gray-100);
/* Text */
--text-primary: var(--gray-900);
--text-secondary: var(--gray-500);
--text-muted: var(--gray-400);
/* Borders */
--border-subtle: var(--gray-200);
--border-default: var(--gray-300);
--border-emphasis: var(--gray-400);
--border-focus: var(--gray-900);
/* Accent */
--accent: var(--primary-600);
--accent-hover: var(--primary-700);
--accent-text: #ffffff;
/* Status */
--color-success: var(--green-500);
--color-error: var(--red-500);
--color-warning: var(--amber-500);
--color-info: var(--blue-500);
/* === COMPONENT TOKENS === */
--button-primary-bg: var(--accent);
--button-primary-text: var(--accent-text);
--button-primary-hover: var(--accent-hover);
--card-bg: var(--bg-elevated);
--card-border: var(--border-subtle);
--input-bg: var(--bg-elevated);
--input-border: var(--border-default);
--input-focus-border: var(--border-focus);
}
.dark, [data-theme="dark"] {
/* Surfaces — lighter = closer */
--bg-base: #121212;
--bg-elevated: #1E1E1E;
--bg-recessed: #0A0A0A;
/* Text — white with opacity */
--text-primary: rgba(255,255,255, 0.87);
--text-secondary: rgba(255,255,255, 0.60);
--text-muted: rgba(255,255,255, 0.38);
/* Borders — white with opacity */
--border-subtle: rgba(255,255,255, 0.06);
--border-default: rgba(255,255,255, 0.10);
--border-emphasis: rgba(255,255,255, 0.15);
--border-focus: #ffffff;
/* Accent — lighter shade for dark bg */
--accent: var(--primary-300);
--accent-hover: var(--primary-200);
/* Status — softer on dark */
--color-success: #34d399;
--color-error: #f87171;
--color-warning: #fbbf24;
--color-info: #60a5fa;
}
:root {
/* Font families */
--font-display: 'DisplayFont', var(--font-display-fallback);
--font-body: 'BodyFont', var(--font-body-fallback);
/* Type scale (Major Third 1.25) */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 4rem; /* 64px */
/* Tracking */
--tracking-tighter: -0.04em;
--tracking-tight: -0.02em;
--tracking-normal: -0.01em;
--tracking-wide: 0.08em;
--tracking-wider: 0.12em;
--tracking-widest: 0.15em;
}
// tailwind.config.js extension
module.exports = {
theme: {
extend: {
colors: {
background: 'var(--bg-base)',
foreground: 'var(--text-primary)',
muted: { DEFAULT: 'var(--bg-recessed)', foreground: 'var(--text-muted)' },
accent: { DEFAULT: 'var(--accent)', foreground: 'var(--accent-text)' },
border: 'var(--border-default)',
input: 'var(--input-border)',
ring: 'var(--border-focus)',
destructive: { DEFAULT: 'var(--color-error)' },
success: { DEFAULT: 'var(--color-success)' },
},
fontFamily: {
display: 'var(--font-display)',
body: 'var(--font-body)',
},
letterSpacing: {
tighter: 'var(--tracking-tighter)',
tight: 'var(--tracking-tight)',
normal: 'var(--tracking-normal)',
wide: 'var(--tracking-wide)',
wider: 'var(--tracking-wider)',
widest: 'var(--tracking-widest)',
},
},
},
};
<!-- Add to <head> to prevent flash of unstyled content on dark mode -->
<script>
(function() {
var theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
})();
</script>
Generate and save:
theme.css — Complete CSS custom properties (light + dark)If the user wants a quick start, offer these curated themes:
| Theme | Primary | Neutral | Mood |
|---|---|---|---|
| Obsidian | slate-blue | cool gray | Professional, tech |
| Terracotta | warm orange | warm gray | Earthy, grounded |
| Midnight | indigo | blue-gray | Deep, sophisticated |
| Bone | near-black | warm white | Minimal, editorial |
| Sage | olive green | warm gray | Natural, calm |
| Ember | deep red | warm gray | Bold, confident |
| Arctic | ice blue | cool gray | Clean, crisp |
| Copper | burnt orange | warm neutral | Warm, industrial |