tailwind-v4-shadcn

Production-ready setup for Tailwind CSS v4 with shadcn/ui, dark mode, and CSS variable architecture. Four-step architecture: define CSS variables at root level with hsl() wrapper, map to Tailwind utilities via @theme inline , apply base styles, and enable automatic dark mode switching Vite plugin-based configuration (no PostCSS or tailwind.config.ts needed); requires @tailwindcss/vite and empty "config" in components.json Semantic color tokens for destructive, success, warning, and info states; dark mode via ThemeProvider with localStorage persistence Common gotchas documented: deprecated tailwindcss-animate package, duplicate @layer base blocks, double-wrapped hsl() values, and wrong plugin syntax using @import instead of @plugin directive

INSTALLATION
npx skills add https://github.com/secondsky/claude-skills --skill tailwind-v4-shadcn
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Tailwind v4 + shadcn/ui Production Stack

Production-tested: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)

Last Updated: 2025-12-04

Status: Production Ready ✅

Table of Contents

  • [Before You Start](#-before-you-start-read-this)
  • [Quick Start](#quick-start-5-minutes---follow-this-exact-order)
  • [Four-Step Architecture](#the-four-step-architecture-critical)
  • [Dark Mode Setup](#dark-mode-setup)
  • [Critical Rules](#critical-rules-must-follow)
  • [Semantic Color Tokens](#semantic-color-tokens)
  • [Common Issues & Fixes](#common-issues--quick-fixes)
  • [File Templates](#file-templates)
  • [Setup Checklist](#complete-setup-checklist)
  • [Advanced Topics](#advanced-topics)
  • [Dependencies](#dependencies)
  • [Tailwind v4 Plugins](#tailwind-v4-plugins)
  • [Reference Documentation](#reference-documentation)
  • [When to Load References](#when-to-load-references)

⚠️ BEFORE YOU START (READ THIS!)

CRITICAL FOR AI AGENTS: If you're Claude Code helping a user set up Tailwind v4:

  • Explicitly state you're using this skill at the start of the conversation
  • Reference patterns from the skill rather than general knowledge
  • Prevent known issues listed in reference/common-gotchas.md
  • Don't guess - if unsure, check the skill documentation

USER ACTION REQUIRED: Tell Claude to check this skill first!

Say: "I'm setting up Tailwind v4 + shadcn/ui - check the tailwind-v4-shadcn skill first"

Why This Matters (Real-World Results)

Without skill activation:

  • ❌ Setup time: ~5 minutes
  • ❌ Errors encountered: 2-3 (tw-animate-css, duplicate @layer base)
  • ❌ Manual fixes needed: 2+ commits
  • ❌ Token usage: ~65k
  • ❌ User confidence: Required debugging

With skill activation:

  • ✅ Setup time: ~1 minute
  • ✅ Errors encountered: 0
  • ✅ Manual fixes needed: 0
  • ✅ Token usage: ~20k (70% reduction)
  • ✅ User confidence: Instant success

Known Issues This Skill Prevents

  • tw-animate-css import error (deprecated in v4)
  • Duplicate @layer base blocks (shadcn init adds its own)
  • Wrong template selection (vanilla TS vs React)
  • Missing post-init cleanup (incompatible CSS rules)
  • Wrong plugin syntax (using @import or require() instead of @plugin directive)

All of these are handled automatically when the skill is active.

Quick Start (5 Minutes - Follow This Exact Order)

1. Install Dependencies

bun add tailwindcss @tailwindcss/vite

# or: npm install tailwindcss @tailwindcss/vite

bun add -d @types/node

# Note: Using pnpm for shadcn init due to known Bun compatibility issues

# (bunx has "Script not found" and postinstall/msw problems)

pnpm dlx shadcn@latest init

2. Configure Vite

// vite.config.ts

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')

    }

  }

})

3. Update components.json

{

  "tailwind": {

    "config": "",              // ← CRITICAL: Empty for v4

    "css": "src/index.css",

    "cssVariables": true

  }

}

4. Delete tailwind.config.ts

rm tailwind.config.ts  # v4 doesn't use this file

The Four-Step Architecture (CRITICAL)

This pattern is mandatory - skipping steps will break your theme.

Step 1: Define CSS Variables at Root Level

/* src/index.css */

@import "tailwindcss";

:root {

  --background: hsl(0 0% 100%);      /* ← hsl() wrapper required */

  --foreground: hsl(222.2 84% 4.9%);

  --primary: hsl(221.2 83.2% 53.3%);

  /* ... all light mode colors */

}

.dark {

  --background: hsl(222.2 84% 4.9%);

  --foreground: hsl(210 40% 98%);

  --primary: hsl(217.2 91.2% 59.8%);

  /* ... all dark mode colors */

}

Critical Rules:

  • ✅ Define at root level (NOT inside @layer base)
  • ✅ Use hsl() wrapper on all color values
  • ✅ Use .dark for dark mode (NOT .dark { @theme { } })

Step 2: Map Variables to Tailwind Utilities

@theme inline {

  --color-background: var(--background);

  --color-foreground: var(--foreground);

  --color-primary: var(--primary);

  /* ... map ALL CSS variables */

}

Why This Is Required:

  • Generates utility classes (bg-background, text-primary)
  • Without this, bg-primary etc. won't exist

Step 3: Apply Base Styles

@layer base {

  body {

    background-color: var(--background);  /* NO hsl() here */

    color: var(--foreground);

  }

}

Critical Rules:

  • ✅ Reference variables directly: var(--background)
  • ❌ Never double-wrap: hsl(var(--background))

Step 4: Result - Automatic Dark Mode

<div className="bg-background text-foreground">

  {/* No dark: variants needed - theme switches automatically */}

</div>

Dark Mode Setup

1. Create ThemeProvider

See reference/dark-mode.md for full implementation or use template:

// Copy from: templates/theme-provider.tsx

2. Wrap Your App

// src/main.tsx

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

ReactDOM.createRoot(document.getElementById('root')!).render(

  <React.StrictMode>

    <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">

      <App />

    </ThemeProvider>

  </React.StrictMode>,

)

3. Add Theme Toggle

pnpm dlx shadcn@latest add dropdown-menu

See reference/dark-mode.md for ModeToggle component code.

Critical Rules (MUST FOLLOW)

✅ Always Do:

-

**Wrap color values with hsl() in :root and .dark**

--background: hsl(0 0% 100%);  /* ✅ Correct */

-

**Use @theme inline to map all CSS variables**

@theme inline {

  --color-background: var(--background);

}

-

**Set "tailwind.config": "" in components.json**

{ "tailwind": { "config": "" } }

-

**Delete tailwind.config.ts if it exists**

-

**Use @tailwindcss/vite plugin (NOT PostCSS)**

-

**Use cn() for conditional classes**

import { cn } from "@/lib/utils"

<div className={cn("base", isActive &#x26;&#x26; "active")} />

❌ Never Do:

-

**Put :root or .dark inside @layer base**

/* WRONG */

@layer base {

  :root { --background: hsl(...); }

}

-

**Use .dark { @theme { } } pattern**

/* WRONG - v4 doesn't support nested @theme */

.dark {

  @theme {

    --color-primary: hsl(...);

  }

}

-

Double-wrap colors

/* WRONG */

body {

  background-color: hsl(var(--background));

}

-

**Use tailwind.config.ts for theme colors**

/* WRONG - v4 ignores this */

export default {

  theme: {

    extend: {

      colors: { primary: 'hsl(var(--primary))' }

    }

  }

}

-

**Use @apply directive (deprecated in v4)**

-

**Use dark: variants for semantic colors**

/* WRONG */

<div className="bg-primary dark:bg-primary-dark" />

/* CORRECT */

<div className="bg-primary" />

Semantic Color Tokens

Always use semantic names for colors:

:root {

  --destructive: hsl(0 84.2% 60.2%);        /* Red - errors, critical */

  --success: hsl(142.1 76.2% 36.3%);        /* Green - success states */

  --warning: hsl(38 92% 50%);               /* Yellow - warnings */

  --info: hsl(221.2 83.2% 53.3%);           /* Blue - info, primary */

}

Usage:

<div className="bg-destructive text-destructive-foreground">Critical</div>

<div className="bg-success text-success-foreground">Success</div>

<div className="bg-warning text-warning-foreground">Warning</div>

<div className="bg-info text-info-foreground">Info</div>

Common Issues &#x26; Quick Fixes

Symptom

Cause

Fix

bg-primary doesn't work

Missing @theme inline mapping

Add @theme inline block

Colors all black/white

Double hsl() wrapping

Use var(--color) not hsl(var(--color))

Dark mode not switching

Missing ThemeProvider

Wrap app in <ThemeProvider>

Build fails

tailwind.config.ts exists

Delete the file

Text invisible

Wrong contrast colors

Check color definitions in :root/.dark

See reference/common-gotchas.md for complete troubleshooting guide.

File Templates

All templates are available in the templates/ directory:

  • index.css - Complete CSS setup with all color variables
  • components.json - shadcn/ui v4 configuration
  • vite.config.ts - Vite + Tailwind plugin setup
  • tsconfig.app.json - TypeScript with path aliases
  • theme-provider.tsx - Dark mode provider with localStorage
  • utils.ts - cn() utility for class merging

Copy these files to your project and customize as needed.

Complete Setup Checklist

  • Vite + React + TypeScript project created
  • @tailwindcss/vite installed (NOT postcss)
  • vite.config.ts uses tailwindcss() plugin
  • tsconfig.json has path aliases configured
  • components.json exists with "config": ""
  • NO tailwind.config.ts file exists
  • src/index.css follows v4 pattern:
  • :root and .dark at root level (not in @layer)
  • Colors wrapped with hsl()
  • @theme inline maps all variables
  • @layer base uses unwrapped variables
  • Theme provider installed and wrapping app
  • Dark mode toggle component created
  • Test theme switching works in browser

Advanced Topics

Load references/advanced-usage.md for advanced patterns including:

  • Custom Colors: Add semantic colors beyond default palette
  • v3 Migration: See references/migration-guide.md for complete guide
  • Component Best Practices: Semantic tokens, cn() utility, composition patterns

Quick Example:

:root { --brand: hsl(280 65% 60%); }

@theme inline { --color-brand: var(--brand); }

Usage: <div className="bg-brand">Branded</div>

For detailed patterns and component composition examples, load references/advanced-usage.md.

Dependencies

✅ Install These

{

  "dependencies": {

    "tailwindcss": "^4.1.17",

    "@tailwindcss/vite": "^4.1.17",

    "clsx": "^2.1.1",

    "tailwind-merge": "^3.3.1",

    "@radix-ui/react-*": "latest",

    "lucide-react": "^0.554.0",

    "react": "^19.2.0",

    "react-dom": "^19.2.0"

  },

  "devDependencies": {

    "@types/node": "^24.10.1",

    "@vitejs/plugin-react": "^5.1.1",

    "vite": "^7.2.4",

    "typescript": "~5.9.3"

  }

}

❌ NEVER Install These (Deprecated in v4)

# These packages will cause build errors:

bun add tailwindcss-animate  # ❌ Deprecated

# or: npm install tailwindcss-animate  # ❌ Deprecated

bun add tw-animate-css      # ❌ Doesn't exist

If you see import errors for these packages, remove them and use native CSS animations or @tailwindcss/motion instead.

Tailwind v4 Plugins

Tailwind v4 supports official plugins using the @plugin directive in CSS.

Quick Example:

@import "tailwindcss";

@plugin "@tailwindcss/typography";

@plugin "@tailwindcss/forms";

Common Error:

❌ WRONG: @import "@tailwindcss/typography" (doesn't work)

✅ CORRECT: @plugin "@tailwindcss/typography" (use @plugin directive)

Built-in Features: Container queries are now core (no @tailwindcss/container-queries plugin needed).

Load references/plugins-reference.md for complete documentation including Typography plugin (prose classes), Forms plugin, installation steps, and common plugin errors.

Reference Documentation

For deeper understanding, see:

  • common-gotchas.md - All the ways it can break (and fixes)
  • dark-mode.md - Complete dark mode implementation
  • migration-guide.md - Migrating hardcoded colors to CSS variables
  • plugins-reference.md - Official Tailwind v4 plugins (Typography, Forms)
  • advanced-usage.md - Custom colors and advanced patterns

When to Load References

Load reference files based on user's specific needs:

Load references/common-gotchas.md when:

  • User reports "colors not working" or "bg-primary doesn't exist"
  • Dark mode not switching properly
  • Build fails with Tailwind errors
  • User encounters any CSS/configuration issue
  • Debugging theme problems

Load references/dark-mode.md when:

  • User asks to implement dark mode
  • Theme switching not working
  • Need ThemeProvider component code
  • Questions about system theme detection

Load references/migration-guide.md when:

  • Migrating from Tailwind v3 to v4
  • User has hardcoded colors to migrate
  • Questions about v3 → v4 changes
  • Need migration checklist

Load references/plugins-reference.md when:

  • User needs Typography plugin (prose class)
  • User needs Forms plugin
  • Questions about @plugin directive
  • Plugin installation errors

Load references/advanced-usage.md when:

  • User asks about custom colors beyond defaults
  • Need advanced component patterns
  • Questions about component best practices
  • Component composition questions

Official Documentation

Secure Installation

When installing Tailwind and shadcn/ui packages, follow supply chain security best practices:

  • Block post-install scriptsnpm config set ignore-scripts true (or Bun: disabled by default)
  • Cooldown period — Wait 7 days for new package versions to be vetted by the community
  • Audit before installing — Run socket package score npm <pkg> or use socket npm install <pkg> to check packages

Load the dependency-upgrade skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.

Production Example

This skill is based on the WordPress Auditor project:

  • Stack: Vite + React 19 + Tailwind v4 + shadcn/ui + Cloudflare Workers
  • Dark Mode: Full system/light/dark support
  • Version: Tailwind v4.1.17 + shadcn/ui latest (Nov 2025)

All patterns in this skill have been validated in production.

Questions? Issues?

  • Check reference/common-gotchas.md first
  • Verify all steps in the 4-step architecture
  • Ensure components.json has "config": ""
  • Delete tailwind.config.ts if it exists
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card