Claude
Skills
Sign in
Back

add-shadcn

Included with Lifetime
$97 forever

Setup a design system using shadcn/ui. Use this skill when the user says "setup design system", "set up design system", "create design system", "setup shadcn", or "initialize design system".

Design

What this skill does


## Quick Start

The `shadcn/ui` initialization supports custom themes via a URL parameter.

**Compatibility:** This skill works with both standard Next.js projects and projects using `--no-src-dir`. The component paths (`components/`) automatically adapt to your project structure.

Use this command

```bash
bunx shadcn@latest create $(jq -r .name package.json) --preset "https://ui.shadcn.com/init?base=base&baseColor=gray&theme=emerald&iconLibrary=phosphor&radius=none&style=maia&font=nunito-sans&menuAccent=subtle&menuColor=default&template=next" --template next
```

After initialization, auto-fix formatting and lint issues in generated components:

```bash
bunx biome format --write . && bunx biome check --fix .
```

**Note:** The `format` step fixes whitespace/style, and the `check --fix` step fixes import sorting (`organizeImports`) in shadcn-generated files. Both are required — shadcn components ship with unsorted imports that fail `biome check`.

### Remove Demo Component

The shadcn preset includes a demo `component-example.tsx` file. Remove it:

```bash
rm -f src/components/component-example.tsx components/component-example.tsx
```

### Update globals.css

After initialization, add the following to `app/globals.css` (or `src/app/globals.css`) inside the `@layer base` block, or as a top-level rule:

```css
html {
  @apply h-dvh overscroll-none;
}
```

This ensures the app fills the dynamic viewport height on mobile and prevents overscroll bounce effects.

### Enforce Monochrome Dark Mode Grays (Required)

After initialization, **always** post-process the `.dark` theme block in `globals.css` to remove chroma from all neutral gray variables. shadcn themes sometimes generate dark grays with blue or purple tint (non-zero chroma in oklch). Mixing these tinted grays with components that use pure neutrals (e.g., React Flow, canvas elements, third-party widgets) creates an ugly warm/cold mismatch.

**Rule:** Every oklch color in the `.dark {}` block that represents a **neutral gray** (background, card, popover, muted, accent, secondary, sidebar, ring, foreground) must have **chroma set to 0**. Only accent colors like `--primary`, `--destructive`, and `--chart-*` should retain chroma.

For example, if shadcn generates:

```css
.dark {
  --background: oklch(0.13 0.028 261.692);
  --card: oklch(0.21 0.034 264.665);
  --muted: oklch(0.278 0.033 256.848);
  --muted-foreground: oklch(0.707 0.022 261.325);
}
```

Post-process to:

```css
.dark {
  --background: oklch(0.13 0 0);
  --card: oklch(0.18 0 0);
  --muted: oklch(0.22 0 0);
  --muted-foreground: oklch(0.65 0 0);
}
```

**Variables to make monochrome (chroma=0, hue=0):**
`--background`, `--foreground`, `--card`, `--card-foreground`, `--popover`, `--popover-foreground`, `--secondary`, `--secondary-foreground`, `--muted`, `--muted-foreground`, `--accent`, `--accent-foreground`, `--border`, `--input`, `--ring`, `--sidebar`, `--sidebar-foreground`, `--sidebar-accent`, `--sidebar-accent-foreground`

**Variables to keep as-is (retain generated chroma):**
`--primary`, `--primary-foreground`, `--destructive`, `--chart-1` through `--chart-5`, `--sidebar-primary`, `--sidebar-primary-foreground`

After initialization, if an `AGENTS.md` file exists at the project root, verify it documents the Base UI and Phosphor icon conventions. The `create-next` skill creates this file with the correct conventions.

## Multi-Registry Configuration

shadcn/ui supports multiple component registries beyond the official library. This enables access to specialized components from third-party sources.

### Recommended Registries

**React Bits** - Animated and interactive components

- URL: <https://reactbits.dev/>
- Installation: `npx shadcn add @react-bits/<component>`

**ElevenLabs UI** - Agent and audio components

- URL: <https://ui.elevenlabs.io/>
- Installation: `npx shadcn add @elevenlabs-ui/<component>`

**MapCN** - Map components built on MapLibre

- URL: <https://mapcn.dev/>
- Installation: `npx shadcn add @mapcn/<component>`

### Configure Custom Registries

After running `shadcn init`, your `components.json` file supports namespace-based registries. Add custom registries to the configuration:

```json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "base-maia",
  "registries": {
    "@react-bits": {
      "url": "https://reactbits.dev"
    },
    "@elevenlabs-ui": {
      "url": "https://ui.elevenlabs.io"
    },
    "@mapcn": {
      "url": "https://mapcn.dev"
    }
  }
}
```

**Note:** Most community registries work without explicit configuration - the CLI discovers them automatically. The registries section is only needed for private or custom registries.

### Using Components from Different Registries

```bash
# Official shadcn components
bunx shadcn@latest add button

# React Bits - animated components
bunx shadcn@latest add @react-bits/animated-card

# ElevenLabs - audio player
bunx shadcn@latest add @elevenlabs-ui/audio-player

# MapCN - interactive maps
bunx shadcn@latest add @mapcn/map-viewer
```

### MCP Server for Natural Language Component Discovery

The shadcn MCP server enables AI-assisted component discovery and installation using natural language.

**Setup:**

```bash
# Install shadcn MCP server (if using Claude Code or compatible IDE)
# Configuration is typically added to your MCP settings
```

**Usage:**
Ask your AI assistant to find and install components:

- "Find me a login form from the shadcn registry"
- "Install an animated card component from React Bits"
- "Add a map component for displaying locations"

The MCP server works with:

- Official shadcn/ui registry
- Third-party component libraries (React Bits, ElevenLabs UI, MapCN, etc.)
- Private company registries (requires authentication via `.env.local`)

## Dark Mode Setup (Required)

After running the shadcn init command, dark mode requires additional setup.

### 1. Install Dependencies

```bash
bun add next-themes
```

### 2. Create ThemeProvider Component

Create `components/theme-provider.tsx`:

```tsx
"use client";

import { ThemeProvider as NextThemesProvider } from "next-themes";

type ThemeProviderProps = React.ComponentProps<typeof NextThemesProvider>;

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}
```

### 3. Create ModeToggle Component

**Note:** The preset includes the `dropdown-menu` component, so no additional installation is needed.

Create `components/mode-toggle.tsx`:

```tsx
"use client";

import { Moon, Sun } from "@phosphor-icons/react";
import { useTheme } from "next-themes";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

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

  return (
    <DropdownMenu>
      <DropdownMenuTrigger className="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 w-10 shrink-0 cursor-pointer">
        <Sun size={20} className="scale-100 rotate-0 transition-transform dark:scale-0 dark:-rotate-90" />
        <Moon size={20} className="absolute scale-0 rotate-90 transition-transform dark:scale-100 dark:rotate-0" />
        <span className="sr-only">Toggle theme</span>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={() => setTheme("light")}>
          Light
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("dark")}>
          Dark
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("system")}>
          System
        </DropdownMenuItem>
      </DropdownMenuContent>
  
Files: 1
Size: 15.8 KB
Complexity: 24/100
Category: Design

Related in Design