Beginner12 min1 prerequisite

Install and configure shadcn/ui in your Next.js project with the CLI and manual setup options.

Installation & Setup

Get shadcn/ui running in your Next.js project. The CLI handles most configuration automatically.

Prerequisites

Before installing shadcn/ui, ensure you have:

  • Next.js 13.4+ with App Router
  • Tailwind CSS configured
  • TypeScript (recommended)

CLI Installation

Initialize shadcn/ui

Terminal
npx shadcn@latest init

The CLI will ask several questions:

Terminal
Which style would you like to use? › New York
Which color would you like to use as base color? › Zinc
Do you want to use CSS variables for colors? › yes

Style Options

Default - Rounded corners, subtle shadows

Terminal
Border radius: 0.5rem
Softer appearance

New York - Sharper edges, more contrast

Terminal
Border radius: 0.3rem
Bolder, more defined look

Base Colors

Choose your neutral color palette:

ColorDescriptionBest For
SlateBlue-gray undertonesModern, professional
GrayPure neutralMinimal, clean
ZincWarm grayBalanced, versatile
NeutralTrue neutralMaximum flexibility
StoneWarm undertonesOrganic, friendly

CSS Variables

Recommended: Yes

Using CSS variables enables:

  • Runtime theme switching
  • Dark mode support
  • Easy color customization

Generated Files

After initialization, shadcn/ui creates:

Terminal
project/
├── components/
│   └── ui/           # Component files go here
├── lib/
│   └── utils.ts      # cn() utility function
├── app/
│   └── globals.css   # Updated with CSS variables
├── components.json   # shadcn/ui configuration
└── tailwind.config.ts # Updated configuration

components.json

Configuration file for the CLI:

Terminal
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "app/globals.css",
    "baseColor": "zinc",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  }
}

The utils.ts File

Terminal
// lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

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

This utility merges Tailwind classes intelligently.

Updated globals.css

Tailwind v4 (Current):

Terminal
@import "tailwindcss";

@theme {
  /* shadcn/ui CSS variables */
  --color-background: hsl(var(--background));
  --color-foreground: hsl(var(--foreground));
  --color-primary: hsl(var(--primary));
  --color-primary-foreground: hsl(var(--primary-foreground));
  /* ... other theme colors */
  --radius-lg: var(--radius);
}

:root {
  --background: 0 0% 100%;
  --foreground: 240 10% 3.9%;
  --primary: 240 5.9% 10%;
  --primary-foreground: 0 0% 98%;
  --secondary: 240 4.8% 95.9%;
  --secondary-foreground: 240 5.9% 10%;
  --muted: 240 4.8% 95.9%;
  --muted-foreground: 240 3.8% 46.1%;
  --accent: 240 4.8% 95.9%;
  --accent-foreground: 240 5.9% 10%;
  --destructive: 0 84.2% 60.2%;
  --destructive-foreground: 0 0% 98%;
  --border: 240 5.9% 90%;
  --input: 240 5.9% 90%;
  --ring: 240 5.9% 10%;
  --radius: 0.5rem;
}

.dark {
  --background: 240 10% 3.9%;
  --foreground: 0 0% 98%;
  /* ... dark mode variables */
}

* {
  @apply border-border;
}
body {
  @apply bg-background text-foreground;
}

Tailwind v3 (Legacy):

Terminal
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    /* ... same variables */
  }
}

Note: shadcn/ui CLI v4+ automatically generates Tailwind v4-compatible CSS.

Adding Components

Using the CLI

Add components as needed:

Terminal
# Add a single component
npx shadcn@latest add button

# Add multiple components
npx shadcn@latest add button card input

# Add all components (not recommended)
npx shadcn@latest add --all

What Happens When You Add

Terminal
npx shadcn@latest add button
  1. CLI downloads component code
  2. Places it in components/ui/button.tsx
  3. Installs any required dependencies
  4. Component is ready to use

Component Dependencies

Some components require others:

Terminal
# Dialog requires these dependencies
npx shadcn@latest add dialog
# Installs: @radix-ui/react-dialog
Terminal
# Form requires multiple packages
npx shadcn@latest add form
# Installs: react-hook-form, @hookform/resolvers, zod

Manual Installation

If you prefer manual setup or need custom configuration:

1. Install Dependencies

Terminal
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge
npm install @radix-ui/react-slot

2. Create utils.ts

Terminal
// lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

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

3. Update tailwind.config.ts

Terminal
import type { Config } from "tailwindcss"

const config: Config = {
  darkMode: ["class"],
  content: [
    "./pages/**/*.{ts,tsx}",
    "./components/**/*.{ts,tsx}",
    "./app/**/*.{ts,tsx}",
  ],
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
      borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
}

export default config

4. Copy Components Manually

Copy component code from the shadcn/ui website or GitHub repository.

Path Aliases

shadcn/ui expects path aliases. Ensure your tsconfig.json includes:

Terminal
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  }
}

This enables imports like:

Terminal
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

AI Tool Setup

v0 Projects

v0 includes shadcn/ui by default. No setup needed.

Lovable/Bolt Projects

Usually pre-configured. Check for components.json:

Terminal
# If missing, run init
npx shadcn@latest init

Claude Code Projects

Ask Claude Code to set up shadcn/ui:

Terminal
Set up shadcn/ui in this Next.js project with the New York style

Verifying Installation

After setup, test with a component:

Terminal
npx shadcn@latest add button
Terminal
// app/page.tsx
import { Button } from "@/components/ui/button"

export default function Home() {
  return (
    <div className="p-8">
      <Button>Click me</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="destructive">Delete</Button>
    </div>
  )
}

If buttons render correctly with proper styling, setup is complete.

Troubleshooting

"Module not found" Errors

Check path aliases in tsconfig.json:

Terminal
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./*"]
    }
  }
}

Styles Not Applying

Ensure globals.css is imported in your root layout:

Terminal
// app/layout.tsx
import "./globals.css"

Dark Mode Not Working

  1. Check darkMode: ["class"] in tailwind.config.ts
  2. Ensure dark mode CSS variables are in globals.css
  3. Use a theme provider like next-themes

Component Import Errors

Verify the component was added:

Terminal
ls components/ui/

If missing, add it:

Terminal
npx shadcn@latest add [component-name]

Summary

  • CLI Installation: npx shadcn@latest init handles configuration
  • Add Components: npx shadcn@latest add [component]
  • Key Files: components.json, utils.ts, globals.css
  • Path Aliases: Required for @/ imports
  • CSS Variables: Enable theming and dark mode

Next Steps

Learn how to use and compose shadcn/ui components in your applications.

Mark this lesson as complete to track your progress