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