Skip to main content
ClaudeWave
EN, English
Skill1.1k repo starsupdated 19d ago

tailwind-theme-builder

The tailwind-theme-builder skill configures a complete Tailwind v4 and shadcn/ui project with CSS variable-based theming and dark mode support. Use it when setting up new Tailwind v4 projects, implementing shadcn/ui color systems, troubleshooting dark mode switching, resolving @theme inline conflicts, fixing @apply errors after v3 to v4 migration, or debugging non-functional themed components.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/jezweb/claude-skills /tmp/tailwind-theme-builder && cp -r /tmp/tailwind-theme-builder/plugins/frontend/skills/tailwind-theme-builder ~/.claude/skills/tailwind-theme-builder
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Tailwind Theme Builder

Set up a fully themed Tailwind v4 + shadcn/ui project with dark mode. Produces configured CSS, theme provider, and working component library.

## Architecture: The Four-Step Pattern

Tailwind v4 requires a specific architecture for CSS variable-based theming. This pattern is **mandatory** -- skipping or modifying steps breaks the theme.

### How It Works

```
CSS Variable Definition --> @theme inline Mapping --> Tailwind Utility Class
--background           --> --color-background     --> bg-background
(with hsl() wrapper)      (references variable)     (generated class)
```

Dark mode switching:
```
ThemeProvider toggles .dark class on <html>
  --> CSS variables update automatically (.dark overrides :root)
  --> Tailwind utilities reference updated variables
  --> UI updates without re-render
```

### Best Practices

- **Semantic names:** Use `--primary` not `--blue-500`
- **Foreground pairing:** Every background colour needs a foreground (`--primary` + `--primary-foreground`)
- **WCAG contrast:** Normal text 4.5:1, large text 3:1, UI components 3:1
- **Chart colours:** Use separate variables with `@theme inline` mapping, reference via `var(--chart-1)` in style props

---

## Workflow

### Step 1: Install Dependencies

```bash
pnpm add tailwindcss @tailwindcss/vite
pnpm add -D @types/node tw-animate-css
pnpm dlx shadcn@latest init

# Delete v3 config if it exists
rm -f tailwind.config.ts
```

### Step 2: Configure Vite

Copy `assets/vite.config.ts` or add the Tailwind plugin:

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: { alias: { '@': path.resolve(__dirname, './src') } }
})
```

### Step 3: Four-Step CSS Architecture (Mandatory)

This exact order is required. Skipping steps breaks the theme.

**src/index.css:**

```css
@import "tailwindcss";
@import "tw-animate-css";

/* 1. Define CSS variables at root (NOT inside @layer base) */
:root {
  --background: hsl(0 0% 100%);
  --foreground: hsl(222.2 84% 4.9%);
  --primary: hsl(221.2 83.2% 53.3%);
  --primary-foreground: hsl(210 40% 98%);
  /* ... all semantic tokens */
}

.dark {
  --background: hsl(222.2 84% 4.9%);
  --foreground: hsl(210 40% 98%);
  --primary: hsl(217.2 91.2% 59.8%);
  --primary-foreground: hsl(222.2 47.4% 11.2%);
}

/* 2. Map variables to Tailwind utilities */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
}

/* 3. Apply base styles (NO hsl() wrapper here) */
@layer base {
  body {
    background-color: var(--background);
    color: var(--foreground);
  }
}
```

**Result:** `bg-background`, `text-primary` etc. work automatically. Dark mode switches via `.dark` class -- no `dark:` variants needed for semantic colours.

### Step 4: Set Up Dark Mode

Copy `assets/theme-provider.tsx` to your components directory, then wrap your app:

```typescript
import { ThemeProvider } from '@/components/theme-provider'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
    <App />
  </ThemeProvider>
)
```

Add a theme toggle -- install the dropdown menu then use the ModeToggle component below:

```bash
pnpm dlx shadcn@latest add dropdown-menu
```

```typescript
// src/components/mode-toggle.tsx
import { Moon, Sun } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { useTheme } from "@/components/theme-provider"

export function ModeToggle() {
  const { setTheme } = useTheme()

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="icon">
          <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
          <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
          <span className="sr-only">Toggle theme</span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("dark")}>Dark</DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("system")}>System</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}
```

### Step 5: Configure components.json

```json
{
  "tailwind": {
    "config": "",
    "css": "src/index.css",
    "baseColor": "slate",
    "cssVariables": true
  }
}
```

`"config": ""` is critical -- v4 doesn't use tailwind.config.ts.

---

## Critical Rules

**Always:**
- Wrap colours with `hsl()` in `:root`/`.dark`
- Use `@theme inline` to map all CSS variables
- Use `@tailwindcss/vite` plugin (NOT PostCSS)
- Delete `tailwind.config.ts` if it exists

**Never:**
- Put `:root`/`.dark` inside `@layer base`
- Use `.dark { @theme { } }` (v4 doesn't support nested @theme)
- Double-wrap: `hsl(var(--background))`
- Use `@apply` with `@layer base` classes (use `@utility` instead)

---

## All 18 Gotchas

### Quick Diagnosis

| # | Symptom | Cause | Fix |
|---|---------|-------|-----|
| 1 | Variables ignored / theme broken | `:root` inside `@layer base` | Move `:root` and `.dark` to root level |
| 2 | Dark mode colours not switching | `.dark { @theme { } }` | Use CSS variables + single `@theme inline` |
| 3 | Colours all black/white | Double `hsl()` wrapping | Use `var(--background)` not `hsl(var(...))` |
| 4 | `bg-primary` not generated | Colours in `tailwind.config.ts` | Delete config, use `@theme inline` |
| 5 | `bg-background` class missing | No `@theme inline` block | Add `@theme inline`
ai-image-generatorSkill

Generate AI images using Gemini or GPT APIs directly. Covers model selection (Gemini for scenes; GPT Image 2 for text rendering, batch variations, multi-reference compositing; GPT Image 1.5 for transparent icons), the 5-part prompting framework, API calling patterns, multi-turn editing, and quality assurance. Produces photorealistic scenes, icons, illustrations, OG images, posters, infographics, and product shots. Use when building websites that need images, creating marketing assets, or generating visual content. Triggers: 'generate image', 'ai image', 'create hero image', 'make an icon', 'generate illustration', 'create og image', 'poster', 'infographic', 'image variations', 'gpt-image-2', 'ai art', 'image generation'.

app-docsSkill

Generate complete user documentation for a web app with screenshots. Browses the app via browser automation, screenshots every screen, and produces a structured user guide with step-by-step instructions, annotated screenshots, workflow diagrams, and reference tables. Supports quick (key screens), standard (all pages), thorough (every state and flow), and exhaustive (publishable documentation suite). Triggers: 'document the app', 'user guide', 'app documentation', 'screenshot docs', 'generate user docs', 'help docs', 'how-to guide', 'write the docs'.

aussie-business-englishSkill

Australian business English for professional writing — warm, direct, EN-AU spelling (colour, organise, centre), no filler words. Use whenever the user is writing for an Australian audience: emails, chat messages, proposals, client communications, blog posts, web copy, or any business writing. Apply to drafting, editing, and tone-checking professional text.

award-applicationSkill

Write compelling award submissions, grant applications, and competition entries. Maps achievements to selection criteria using evidence-based narratives. Use whenever the user is applying for a business award (Telstra, chamber of commerce, industry awards), a grant, a competition, or any submission demonstrating merit against defined criteria.

brains-trustSkill

Get a second opinion from leading AI models on code, architecture, strategy, prompting, or anything. Queries models via OpenRouter, Gemini, or OpenAI APIs. Supports single opinion, multi-model consensus, and devil's advocate patterns. Use whenever the user says 'brains trust', 'second opinion', 'ask gemini', 'ask gpt', 'peer review', 'consult another model', 'challenge this', or 'devil's advocate'.

cloudflare-apiSkill

Hit the Cloudflare REST API directly for operations that wrangler and MCP can't handle well. Bulk DNS, custom hostnames, email routing, cache purge, WAF rules, redirect rules, zone settings, Worker routes, D1 cross-database queries, R2 bulk operations, KV bulk read/write, Vectorize queries, Queues, and fleet-wide resource audits. Produces curl commands or scripts. Triggers: 'cloudflare api', 'bulk dns', 'custom hostname', 'email routing', 'cache purge', 'waf rule', 'd1 query', 'r2 bucket', 'kv bulk', 'vectorize query', 'audit resources', 'fleet operation'.

cloudflare-worker-builderSkill

Scaffold and deploy Cloudflare Workers with Hono routing, Vite plugin, and Static Assets. Describe project, scaffold structure, configure bindings, deploy. Use whenever the user wants to create a Worker project, set up Hono on Cloudflare, configure D1 / R2 / KV / Queues bindings, or troubleshoot Worker export syntax, API route conflicts, HMR issues, or deployment failures.

codex-reviewSkill

Run an independent code review using the OpenAI Codex CLI in headless mode. Gets a second opinion from a different model family (the current Codex models) on recent changes, a PR, a commit, or the whole app — covering bugs, regressions, security, data consistency, UX/state bugs, performance risks, and testing gaps. Saves a severity-prioritised report to .jez/reviews/. Triggers: 'codex review', 'review with codex', 'independent code review', 'what does codex think', 'get codex to review'.