npx claudepluginhub secondsky/claude-skills --plugin tailwind-v4-shadcnThis skill uses the workspace's default tool permissions.
**Production-tested**: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)
Applies Acme Corporation brand guidelines including colors, fonts, layouts, and messaging to generated PowerPoint, Excel, and PDF documents.
Builds DCF models with sensitivity analysis, Monte Carlo simulations, and scenario planning for investment valuation and risk assessment.
Calculates profitability (ROE, margins), liquidity (current ratio), leverage, efficiency, and valuation (P/E, EV/EBITDA) ratios from financial statements in CSV, JSON, text, or Excel for investment analysis.
Production-tested: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev) Last Updated: 2025-12-04 Status: Production Ready ✅
CRITICAL FOR AI AGENTS: If you're Claude Code helping a user set up Tailwind v4:
reference/common-gotchas.mdUSER 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"
Without skill activation:
With skill activation:
All of these are handled automatically when the skill is active.
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
// 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')
}
}
})
{
"tailwind": {
"config": "", // ← CRITICAL: Empty for v4
"css": "src/index.css",
"cssVariables": true
}
}
rm tailwind.config.ts # v4 doesn't use this file
This pattern is mandatory - skipping steps will break your theme.
/* 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:
@layer base)hsl() wrapper on all color values.dark for dark mode (NOT .dark { @theme { } })@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
/* ... map ALL CSS variables */
}
Why This Is Required:
bg-background, text-primary)bg-primary etc. won't exist@layer base {
body {
background-color: var(--background); /* NO hsl() here */
color: var(--foreground);
}
}
Critical Rules:
var(--background)hsl(var(--background))<div className="bg-background text-foreground">
{/* No dark: variants needed - theme switches automatically */}
</div>
See reference/dark-mode.md for full implementation or use template:
// Copy from: templates/theme-provider.tsx
// 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>,
)
pnpm dlx shadcn@latest add dropdown-menu
See reference/dark-mode.md for ModeToggle component code.
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 && "active")} />
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" />
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>
| 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.
All templates are available in the templates/ directory:
cn() utility for class mergingCopy these files to your project and customize as needed.
@tailwindcss/vite installed (NOT postcss)vite.config.ts uses tailwindcss() plugintsconfig.json has path aliases configuredcomponents.json exists with "config": ""tailwind.config.ts file existssrc/index.css follows v4 pattern:
:root and .dark at root level (not in @layer)hsl()@theme inline maps all variables@layer base uses unwrapped variablesLoad references/advanced-usage.md for advanced patterns including:
references/migration-guide.md for complete guideQuick 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": {
"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"
}
}
# 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 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.
For deeper understanding, see:
Load reference files based on user's specific needs:
references/common-gotchas.md when:references/dark-mode.md when:references/migration-guide.md when:references/plugins-reference.md when:references/advanced-usage.md when:This skill is based on the WordPress Auditor project:
All patterns in this skill have been validated in production.
Questions? Issues?
reference/common-gotchas.md firstcomponents.json has "config": ""tailwind.config.ts if it exists