# Shadcn Setup

> Sets up shadcn/ui with Tailwind CSS v4 CSS-first configuration — installs packages, generates globals.css with @theme tokens, creates components.json, and adds the cn() utility. Use when starting a new Next.js or React project that needs a shadcn component library, or migrating from shadcn + Tailwind v3.

- Skill: `shipshitdev/shadcn-setup-2` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add shipshitdev/shadcn-setup-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/shipshitdev/shadcn-setup-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: shipshitdev (https://skillmd.com/u/shipshitdev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/shipshitdev/shadcn-setup-2

---


# shadcn/ui Setup

Sets up shadcn/ui with proper Tailwind CSS v4 configuration. This skill ensures you get the modern CSS-first setup, not the deprecated v3 approach.

## Contract

Inputs:

- Project root directory (defaults to current working directory).
- Optional: theme name (zinc, slate, stone, etc.), component list, router type (app-router or pages-router).

Outputs:

- `globals.css` with `@import "tailwindcss"` and full `@theme` token block.
- `components.json` with CSS-first shadcn config.
- `src/lib/utils.ts` with `cn()` helper.
- Installed packages: `class-variance-authority`, `clsx`, `tailwind-merge`, `lucide-react`, `tailwindcss`, `@tailwindcss/postcss`.

Creates/Modifies:

- `src/app/globals.css` (created or overwritten).
- `components.json` (created or overwritten).
- `src/lib/utils.ts` (created).
- `package.json` (dependencies updated via `bun add`).
- `postcss.config.mjs` (created if absent).

External Side Effects:

- Runs `bun add` to install packages.
- Runs `bunx shadcn@latest add` for any specified components.

Confirmation Required:

- None. Running this skill applies all changes immediately. Review the component list before invoking in an existing project.

Delegates To:

- `bunx shadcn@latest add` for individual component installation.

## Purpose

**IMPORTANT**: shadcn/ui CLI and AI assistants often generate Tailwind v3 configs by default. This skill ensures:

- Tailwind v4 CSS-first configuration
- Proper `@theme` block with shadcn color tokens
- No deprecated `tailwind.config.js` files
- Correct dependency versions

## When to Use

- Setting up a new Next.js project with shadcn/ui
- Adding shadcn/ui to an existing project
- Migrating from shadcn + Tailwind v3 to v4
- Resetting a broken shadcn configuration

## Quick Start

```bash
# Install core dependencies
bun add class-variance-authority clsx tailwind-merge lucide-react
bun add -D tailwindcss @tailwindcss/postcss

# Initialize shadcn (CSS-first, no tailwind.config)
bunx shadcn@latest init

# Install specific components
bunx shadcn@latest add button card input dialog

# Or install an essential starter set
bunx shadcn@latest add button card input label dialog dropdown-menu toast
```

## What Gets Installed

### Dependencies

```json
{
  "dependencies": {
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.0",
    "tailwind-merge": "^2.2.0",
    "lucide-react": "^0.400.0"
  },
  "devDependencies": {
    "tailwindcss": "^4.0.0",
    "@tailwindcss/postcss": "^4.0.0"
  }
}
```

### File Structure

```
project/
├── src/
│   ├── app/
│   │   └── globals.css           # Tailwind v4 + shadcn theme
│   ├── components/
│   │   └── ui/                   # shadcn components
│   │       ├── button.tsx
│   │       ├── card.tsx
│   │       └── ...
│   └── lib/
│       └── utils.ts              # cn() utility
├── components.json               # shadcn config
└── postcss.config.mjs            # PostCSS with @tailwindcss/postcss
```

## Tailwind v4 + shadcn CSS Configuration

The skill generates a CSS-first configuration using `@import "tailwindcss"` and an `@theme` block with all shadcn color tokens and border-radius variables.

See `${CLAUDE_SKILL_DIR}/references/shadcn-theme-tokens.md` for the full token block (load when constructing the globals.css file).

## Available Themes

| Theme | Description |
|-------|-------------|
| `default` | shadcn default (neutral grays) |
| `zinc` | Zinc-based neutral |
| `slate` | Slate-based cool neutral |
| `stone` | Stone-based warm neutral |
| `gray` | Pure gray |
| `neutral` | True neutral |
| `red` | Red primary |
| `rose` | Rose primary |
| `orange` | Orange primary |
| `green` | Green primary |
| `blue` | Blue primary |
| `yellow` | Yellow primary |
| `violet` | Violet primary |

## Common Components

Install commonly used components:

```bash
# Essential set
bunx shadcn@latest add button card input label dialog dropdown-menu toast

# Form-focused
bunx shadcn@latest add form input label select checkbox radio-group switch textarea

# Dashboard
bunx shadcn@latest add card table tabs badge avatar dropdown-menu sheet sidebar
```

## components.json Configuration

```json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/app/globals.css",
    "baseColor": "zinc",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "iconLibrary": "lucide"
}
```

**Note**: The `tailwind.config` is empty because we use CSS-first configuration in v4.

## Utils File

```typescript
// src/lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
```

## Usage After Setup

### Adding Components

```bash
# Using bunx (recommended with bun)
bunx shadcn@latest add button

# Multiple components
bunx shadcn@latest add card dialog dropdown-menu
```

### Using Components

```tsx
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';

export function MyComponent() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Welcome</CardTitle>
      </CardHeader>
      <CardContent>
        <Button>Click me</Button>
      </CardContent>
    </Card>
  );
}
```

## Dark Mode Support

The CSS uses `prefers-color-scheme` by default. For manual toggle:

```tsx
// Add to layout.tsx or a theme provider
'use client';

import { useEffect, useState } from 'react';

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  useEffect(() => {
    document.documentElement.classList.toggle('dark', theme === 'dark');
  }, [theme]);

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}
```

Update CSS to use class-based dark mode:

```css
/* Replace @media (prefers-color-scheme: dark) with: */
.dark {
  --color-background: hsl(222.2 84% 4.9%);
  /* ... rest of dark theme variables */
}
```

## Troubleshooting

### "tailwind.config.js created by shadcn CLI"

Delete it. The CLI sometimes generates v3 configs. Run:

```bash
rm tailwind.config.js tailwind.config.ts
```

### Components not styled correctly

1. Check that `globals.css` is imported in your layout
2. Verify `@import "tailwindcss"` is at the top
3. Ensure `@theme` block contains all required variables

### Type errors with components

Run:

```bash
bun add -D @types/react @types/react-dom
```

### cn() utility not found

Create `src/lib/utils.ts`:

```typescript
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
```

## Validation

After setup, verify no v3 patterns were introduced:

```bash
# Should return nothing (no v3 tailwind.config files)
find . -name "tailwind.config.*" -not -path "*/node_modules/*"

# Should return nothing (no @apply directives)
grep -r "@apply" src/ --include="*.css" 2>/dev/null

# Verify the @import directive is present
grep "@import \"tailwindcss\"" src/app/globals.css
```

