shadcn/ui is a CLI-driven component registry that copies beautifully designed, accessible React UI components directly into your project. Unlike traditional component libraries installed as npm dependencies, shadcn/ui gives you full ownership of every component — the source code lives in your repo, you control it, and you can customize it however you want. Components are built on Radix UI or Base UI primitives and styled with Tailwind CSS.
This guide covers the shadcn CLI (version 4.3.0), every command and option, project setup across all supported frameworks, and real-world recipes for common tasks.
1. Quick Start
What is shadcn/ui?
shadcn/ui is not a component library you npm install. It is a CLI tool (shadcn) that fetches component source code from a registry and copies it into your project. You get the actual .tsx files in your codebase — no black-box dependency, no version lock-in. When you need to change how a button looks or a dialog behaves, you edit the file directly.
Key Features
- Copy-paste architecture — components live in your repo, not
node_modules - 12 CLI commands — init, add, apply, search, build, migrate, diff, docs, view, info, mcp, registry
- 6 framework templates — Next.js, Vite, React Router, TanStack Start, Astro, Laravel
- 2 component bases — Radix UI (default) or Base UI (MUI)
- Tailwind CSS styling — CSS variables, dark mode, RTL support out of the box
- Custom registries — host and share your own component sets
- MCP server — integrate with AI coding tools (Claude Code, Cursor, VS Code, Codex, OpenCode)
- Monorepo support — automatic workspace detection and file distribution
Prerequisites
| Requirement | Minimum Version |
|---|---|
| Node.js | 20+ |
| Package manager | npm, pnpm, yarn, or bun |
| React | 18+ (19 recommended) |
| Tailwind CSS | v3 or v4 |
Fastest Way to Start
Create a new Next.js project with shadcn/ui in one command:
npx shadcn@latest init
This scaffolds a new project, installs dependencies, configures Tailwind CSS, sets up path aliases, and creates a components.json configuration file.
Then add your first component:
npx shadcn@latest add button
Expected output:
✔ Done. Installed 1 component.
- button (components/ui/button.tsx)
Use it in your code:
import { Button } from "@/components/ui/button"
export default function Home() {
return <Button variant="outline">Click me</Button>
}
What to Try Next
- Adding components — install any of 50+ components
- Project initialization — set up with your framework of choice
- Configuration — customize paths, aliases, and theming
- Common Tasks — real-world recipes and workflows
2. Installation
System Requirements
| Component | Requirement | Notes |
|---|---|---|
| Node.js | v20 or later | Required for the CLI |
| npm / pnpm / yarn / bun | Any recent version | CLI auto-detects your package manager |
| Git | Any recent version | Required for project scaffolding |
| Operating System | macOS, Linux, Windows | All platforms supported |
| Disk Space | ~50 MB | For CLI + dependencies |
Install Methods
Note
You do not install
shadcnas a global package. Instead, use your package manager's exec command to run it directly. This ensures you always use the latest version.
npm
npx shadcn@latest init
pnpm
pnpm dlx shadcn@latest init
yarn
yarn dlx shadcn@latest init
bun
bunx shadcn@latest init
All subsequent examples in this guide use npx shadcn@latest. Substitute your preferred package manager's exec command as shown above.
Post-Install Verification
After running init, verify your setup:
- Check that
components.jsonexists at your project root:
cat components.json
You should see a JSON file with $schema, style, aliases, and tailwind fields.
- Check that the utils file was created:
ls src/lib/utils.ts
- Run the info command to confirm the CLI can read your project:
npx shadcn@latest info
This prints your framework, component base, style, and alias configuration.
Install Troubleshooting
npm error Invalid Version
This occurs when your Node.js version is below 20. Upgrade Node.js:
node --version # Must be v20+
EACCES: permission denied
On Linux/macOS, avoid running with sudo. Instead, fix npm permissions:
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATH
Cannot find module errors after init
Run your package manager's install command to ensure all dependencies are resolved:
npm install
3. Configuration
The components.json File
Every shadcn/ui project has a components.json file at the project root. This file tells the CLI where to put components, what style to use, and how to resolve imports.
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york-v4",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide",
"rtl": false,
"registries": {}
}
Configuration Fields Reference
| Field | Type | Description |
|---|---|---|
$schema |
string | JSON schema URL for validation. Always "https://ui.shadcn.com/schema.json" |
style |
string | Component style preset (e.g., "new-york-v4", "base-nova") |
rsc |
boolean | Enable React Server Components support |
tsx |
boolean | Use TypeScript (.tsx). Set false for JavaScript (.jsx) |
tailwind.config |
string | Path to your Tailwind config file |
tailwind.css |
string | Path to your global CSS file |
tailwind.baseColor |
string | Base color palette: "neutral", "zinc", "stone", or "mauve" |
tailwind.cssVariables |
boolean | Use CSS variables for theming (recommended: true) |
tailwind.prefix |
string | Tailwind class prefix (e.g., "tw-" to avoid conflicts) |
aliases.components |
string | Import alias for the components directory |
aliases.utils |
string | Import alias for the utils module |
aliases.ui |
string | Import alias for the UI components directory |
aliases.lib |
string | Import alias for the lib directory |
aliases.hooks |
string | Import alias for the hooks directory |
iconLibrary |
string | Icon library name (e.g., "lucide") |
rtl |
boolean | Enable right-to-left layout support |
menuColor |
string | Menu color mode: "default", "inverted", "default-translucent", "inverted-translucent" |
menuAccent |
string | Menu accent style: "subtle" or "bold" |
registries |
object | Custom registry definitions (see Custom Registries) |
Common Configuration Combinations
Next.js with App Router (TypeScript, Radix, CSS variables)
{
"style": "new-york-v4",
"rsc": true,
"tsx": true,
"tailwind": {
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
}
}
Vite + React (no RSC, Base UI)
{
"style": "base-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
}
}
JavaScript Project (no TypeScript)
{
"tsx": false,
"style": "new-york-v4"
}
Components will be output as .jsx files instead of .tsx.
RTL-Enabled Project
{
"style": "new-york-v4",
"rtl": true
}
Custom Tailwind Prefix (avoiding class collisions)
{
"tailwind": {
"prefix": "tw-",
"cssVariables": true,
"baseColor": "zinc"
}
}
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
REGISTRY_URL |
Override the component registry URL | https://ui.shadcn.com/r |
https_proxy |
HTTP/HTTPS proxy for registry fetches | None |
Set REGISTRY_URL to point at a self-hosted or custom registry:
REGISTRY_URL=https://my-company.com/r npx shadcn@latest add button
Tip
For detailed configuration of custom registries, Tailwind CSS integration, advanced theming, and deployment considerations, see the Admin Guide — Section: Configuration Mastery.
4. Core Usage
This section covers every CLI command organized by user intent — what you want to accomplish and how to do it.
Adding Components
The add command is the most frequently used command. It fetches component source code from a registry and writes it into your project.
Add a Single Component
npx shadcn@latest add button
The CLI resolves the component from the configured registry, downloads its source, resolves any dependencies (other components it needs), installs required npm packages, and writes the files to your configured aliases.ui directory.
Add Multiple Components at Once
npx shadcn@latest add button card dialog input textarea
Each component and its dependencies are resolved and installed together.
Add All Available Components
npx shadcn@latest add -a
or:
npx shadcn@latest add --all
Warning
Adding all components installs 50+ component files and their dependencies into your project. This is useful for exploration but may add significant files to your codebase. Use
--dry-runfirst to preview what will be added.
Add from a URL
You can add components by providing a direct URL to a registry item:
npx shadcn@latest add https://ui.shadcn.com/r/styles/new-york-v4/button.json
This is useful for adding components from third-party registries or specific versions.
Add from a Custom Registry
If you have custom registries configured in components.json, prefix the component name with the registry key:
npx shadcn@latest add my-registry/custom-button
Add from a Local Path
npx shadcn@latest add ./path/to/component.json
Add to a Specific Directory
Override the default output path:
npx shadcn@latest add button -p src/components/custom
Preview Changes Without Writing (Dry Run)
npx shadcn@latest add button --dry-run
This shows what files would be created or modified without actually writing anything to disk. Always a good idea before adding unfamiliar components or using --all.
Overwrite Existing Components
If a component already exists and you want to replace it with the latest version:
npx shadcn@latest add button -o
or:
npx shadcn@latest add button --overwrite
Check What Changed Before Overwriting
View the diff between your local version and the registry version:
npx shadcn@latest add button --diff
View the full registry file contents:
npx shadcn@latest add button --view
Target a specific file path within the component:
npx shadcn@latest add button --diff src/components/ui/button.tsx
npx shadcn@latest add button --view src/components/ui/button.tsx
Skip Confirmation Prompts
npx shadcn@latest add button -y
Silent Mode
Suppress all output:
npx shadcn@latest add button -s
Complete add Options Reference
| Option | Short | Description |
|---|---|---|
[components...] |
Component names, URLs, or local paths | |
--yes |
-y |
Skip confirmation prompt |
--overwrite |
-o |
Overwrite existing files |
--cwd <cwd> |
-c |
Set working directory |
--all |
-a |
Add all available components |
--path <path> |
-p |
Custom output path |
--silent |
-s |
Suppress output |
--dry-run |
Preview without writing files | |
--diff [path] |
Show diff for a component file | |
--view [path] |
Show component file contents |
Initializing a New Project
The init command (alias: create) scaffolds a new project or configures shadcn/ui in an existing project.
Basic Initialization
npx shadcn@latest init
This launches an interactive setup that asks you to choose a framework, component base, style, base color, and alias configuration.
Initialize with Defaults
Skip all prompts and use default settings (Next.js template, base-nova preset):
npx shadcn@latest init -d
or:
npx shadcn@latest init --defaults
Initialize with a Specific Template
npx shadcn@latest init -t vite
Available templates:
| Template | Value | Description |
|---|---|---|
| Next.js | next |
Next.js with App Router |
| Vite | vite |
Vite + React |
| React Router | react-router |
React Router framework mode |
| TanStack Start | start |
TanStack Start with file-based routing |
| Astro | astro |
Astro with React islands |
| Laravel | laravel |
Laravel (requires existing Laravel app) |
Important
The Laravel template does not scaffold a new Laravel project. It configures shadcn/ui within an existing Laravel application. You must have a Laravel app already created.
Initialize with a Component Base
Choose between Radix UI and Base UI primitives:
# Radix UI (default)
npx shadcn@latest init -b radix
# Base UI (MUI)
npx shadcn@latest init -b base
Initialize with a Preset
npx shadcn@latest init -p base-nova
Presets bundle a style, theme, and configuration together for a specific look and feel.
Initialize a Monorepo
npx shadcn@latest init --monorepo
This scaffolds the project as a monorepo with separate workspace packages for UI components, hooks, and library utilities.
To explicitly disable monorepo detection:
npx shadcn@latest init --no-monorepo
Name Your Project
npx shadcn@latest init -n my-app
Force Overwrite Existing Configuration
npx shadcn@latest init -f
Caution
The
--forceflag overwrites your existingcomponents.jsonand related configuration files without warning. Back up your configuration before using this flag.
Enable RTL Support
npx shadcn@latest init --rtl
Disable CSS Variables
npx shadcn@latest init --no-css-variables
Re-install Existing UI Components
After reconfiguring, reinstall all previously added components:
npx shadcn@latest init --reinstall
This re-downloads and regenerates all tracked components using your current configuration.
Complete init Options Reference
| Option | Short | Description |
|---|---|---|
--template <template> |
-t |
Framework template: next, vite, react-router, start, astro, laravel |
--base <base> |
-b |
Component library: radix, base |
--monorepo / --no-monorepo |
Enable/disable monorepo scaffolding | |
--preset [name] |
-p |
Use a preset configuration |
--yes |
-y |
Skip confirmation (default: true) |
--defaults |
-d |
Use defaults: --template=next --preset=base-nova |
--force |
-f |
Force overwrite existing config |
--cwd <cwd> |
-c |
Set working directory |
--name <name> |
-n |
Project name |
--silent |
-s |
Suppress output |
--css-variables / --no-css-variables |
Enable/disable CSS variables for theming (default: true) |
|
--rtl / --no-rtl |
Enable/disable RTL support | |
--reinstall / --no-reinstall |
Re-install existing UI components |
Applying Presets
The apply command applies a preset configuration to an existing project. Presets can change style, theme, component variants, and more — all at once.
npx shadcn@latest apply base-nova
or using the --preset flag:
npx shadcn@latest apply --preset base-nova
Apply Options Reference
| Option | Short | Description |
|---|---|---|
[preset] |
Preset name (positional argument) | |
--preset <preset> |
Preset to apply (flag form) | |
--yes |
-y |
Skip confirmation |
--cwd <cwd> |
-c |
Set working directory |
--silent |
-s |
Suppress output |
Note
The
applycommand modifies yourcomponents.jsonand may update existing component files to match the new preset's style. Use version control so you can review and revert changes if needed.
Searching and Browsing Registries
The search command (alias: list) lets you discover available components across registries.
Search All Items in a Registry
npx shadcn@latest search @shadcn
The @shadcn registry is the built-in default pointing to https://ui.shadcn.com/r.
Search with a Query
npx shadcn@latest search @shadcn -q button
Limit and Paginate Results
npx shadcn@latest search @shadcn -q dialog -l 5 -o 0
Search Options Reference
| Option | Short | Description |
|---|---|---|
<registries...> |
One or more registry names to search | |
--query |
-q |
Search query string |
--limit |
-l |
Maximum results to return |
--offset |
-o |
Skip first N results |
Viewing Registry Items
The view command outputs raw JSON data for a registry item. Useful for scripting or inspecting component metadata.
npx shadcn@latest view button
Output is structured JSON containing the component's files, dependencies, and registry metadata.
Getting Component Documentation
The docs command retrieves documentation, API references, and usage examples for a component directly in the terminal.
npx shadcn@latest docs button
This is especially helpful when you want to see all available props, variants, and usage patterns without leaving the terminal or opening a browser.
npx shadcn@latest docs dialog
npx shadcn@latest docs form
npx shadcn@latest docs table
Checking Diffs and Updates
Important
The standalone
diffcommand is deprecated. Useadd [component] --diffinstead.
To see what has changed in a component since you last added it:
npx shadcn@latest add button --diff
To view the current contents of a component from the registry:
npx shadcn@latest add button --view
You can also target a specific file path within the component:
npx shadcn@latest add button --diff src/components/ui/button.tsx
npx shadcn@latest add button --view src/components/ui/button.tsx
This is the recommended workflow for updating components:
- Check the diff:
npx shadcn@latest add button --diff - Review changes
- If acceptable, overwrite:
npx shadcn@latest add button --overwrite
Running Migrations
The migrate command performs automated codebase transformations for common upgrade paths.
Available Migrations
| Migration | Description |
|---|---|
icons |
Migrate to a different icon library |
radix |
Migrate to the radix-ui mono package (replaces individual @radix-ui/* packages) |
rtl |
Add RTL (right-to-left) support to existing components |
Run a Migration
npx shadcn@latest migrate icons
npx shadcn@latest migrate radix
npx shadcn@latest migrate rtl
List Available Migrations
npx shadcn@latest migrate -l
or:
npx shadcn@latest migrate --list
Migration Options Reference
| Option | Short | Description |
|---|---|---|
--list |
-l |
List available migrations |
--yes |
-y |
Skip confirmation |
--cwd <cwd> |
-c |
Set working directory |
Working with the MCP Server
shadcn/ui includes a Model Context Protocol (MCP) server that integrates with AI coding tools. This lets AI assistants add components, search the registry, and read documentation directly through your editor.
Start the MCP Server
npx shadcn@latest mcp
This starts the server using stdio transport. It is designed to be invoked by an MCP client, not run standalone in a terminal.
Initialize MCP Configuration for a Client
npx shadcn@latest mcp init --client cursor
Supported clients:
| Client | Value |
|---|---|
| Claude Code | claude-code |
| Cursor | cursor |
| VS Code | vscode |
| Codex | codex |
| OpenCode | opencode |
This writes the necessary MCP configuration file for your chosen client so it can discover and connect to the shadcn MCP server automatically.
Example: Setting Up MCP for Claude Code
npx shadcn@latest mcp init --client claude-code
After initialization, Claude Code can:
- Add components to your project
- Search the component registry
- Retrieve component documentation and usage examples
- All through natural language commands
Getting Project Information
The info command prints a summary of your shadcn/ui project configuration:
npx shadcn@latest info
Output includes your detected framework, component base, style, Tailwind configuration, aliases, and installed components. Useful for debugging configuration issues or verifying setup.
Building a Custom Registry
The build command compiles your component registry for distribution.
npx shadcn@latest build
By default, this reads ./registry.json and outputs to ./public/r.
Specify a Registry File
npx shadcn@latest build ./my-registry.json
Specify Output Directory
npx shadcn@latest build -o ./dist/r
Build Options Reference
| Option | Short | Description |
|---|---|---|
[registry] |
Path to registry JSON file (default: ./registry.json) |
|
--output <path> |
-o |
Output directory (default: ./public/r) |
Registry Commands
The registry command provides additional registry-related utilities:
npx shadcn@latest registry
5. Common Tasks
Setting Up a Next.js Project from Scratch
# Create and initialize in one step
npx shadcn@latest init -t next -n my-next-app
# Navigate into the project
cd my-next-app
# Add components you need
npx shadcn@latest add button card dialog input label
# Start the dev server
npm run dev
Setting Up a Vite + React Project
npx shadcn@latest init -t vite -n my-vite-app
cd my-vite-app
npx shadcn@latest add button
npm run dev
Setting Up a React Router Project
npx shadcn@latest init -t react-router -n my-rr-app
cd my-rr-app
npx shadcn@latest add button navigation-menu
npm run dev
Setting Up a TanStack Start Project
npx shadcn@latest init -t start -n my-start-app
cd my-start-app
npx shadcn@latest add button
npm run dev
Setting Up an Astro Project
npx shadcn@latest init -t astro -n my-astro-app
cd my-astro-app
npx shadcn@latest add button
npm run dev
Adding shadcn/ui to an Existing Laravel Project
cd existing-laravel-app
npx shadcn@latest init -t laravel
npx shadcn@latest add button card
Adding a Dialog Component and Using It
npx shadcn@latest add dialog
Then in your React code:
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
export function ConfirmDialog() {
return (
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure?</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
)
}
Adding a Form with Validation
npx shadcn@latest add form input label button
The form component integrates with react-hook-form and zod for validation:
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
username: z.string().min(2).max(50),
})
export function ProfileForm() {
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: { username: "" },
})
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
Building a Data Table
npx shadcn@latest add table
The table component provides the structural primitives. Pair with @tanstack/react-table for full data table functionality:
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
export function InvoiceTable() {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>INV001</TableCell>
<TableCell>Paid</TableCell>
<TableCell className="text-right">$250.00</TableCell>
</TableRow>
</TableBody>
</Table>
)
}
Switching from Radix to Base UI
If you started with Radix and want to switch to Base UI:
npx shadcn@latest init -b base -f
Then reinstall your components:
npx shadcn@latest init --reinstall
Tip
The
--reinstallflag re-downloads all previously added components using the new component base. Your customizations will be overwritten — commit your changes first if you want to preserve them.
Setting Up a Monorepo with Shared UI Package
npx shadcn@latest init --monorepo -n my-monorepo
The CLI creates a workspace structure where:
- UI components go to the UI package
- Hooks go to the hooks package
- Library utilities go to the lib package
Each workspace gets its own package.json, and the root components.json maps aliases to the correct workspace paths.
Configuring Dark Mode
shadcn/ui components support dark mode via Tailwind CSS's dark: variant. With CSS variables enabled (the default), theming is controlled through CSS custom properties.
- Ensure
cssVariables: truein yourcomponents.json:
{
"tailwind": {
"cssVariables": true
}
}
- Your global CSS file contains light and dark theme variables:
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
/* ... */
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
/* ... */
}
- Toggle dark mode using your framework's theme provider or by adding/removing the
darkclass on<html>.
For Next.js, the popular approach is next-themes:
import { ThemeProvider } from "next-themes"
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
)
}
Setting Up RTL (Right-to-Left) Support
For RTL layouts (Arabic, Hebrew, Farsi, etc.):
During initialization:
npx shadcn@latest init --rtl
For an existing project — run the RTL migration:
npx shadcn@latest migrate rtl
This transforms component source files to use logical CSS properties and RTL-aware layouts.
Using a Custom Registry
Custom registries let you share components across teams or organizations.
- Define the registry in
components.json:
{
"registries": {
"my-company": {
"url": "https://components.my-company.com/r/{style}/{name}.json"
}
}
}
The {name} and {style} placeholders are replaced at fetch time with the component name and your configured style.
- Add components from your custom registry:
npx shadcn@latest add my-company/custom-button
- Search your custom registry:
npx shadcn@latest search my-company -q button
Building Your Own Registry
- Create a
registry.jsonat your project root:
{
"name": "my-registry",
"items": [
{
"name": "fancy-button",
"type": "registry:ui",
"files": [
{
"path": "registry/fancy-button.tsx",
"type": "registry:ui"
}
]
}
]
}
Registry item types:
| Type | Description |
|---|---|
registry:ui |
UI component |
registry:hook |
React hook |
registry:lib |
Library utility |
registry:theme |
Theme configuration |
registry:style |
Style preset |
registry:base |
Base configuration |
registry:font |
Font configuration |
- Build the registry:
npx shadcn@latest build
This outputs JSON files to ./public/r by default.
- Host the output on any static file server or CDN. Users can then add your registry to their
components.jsonand install your components.
Previewing Changes with --dry-run
Before adding or overwriting components, preview exactly what will change:
npx shadcn@latest add dialog --dry-run
Output shows which files would be created, modified, or have dependencies installed — without writing anything. Combine with --all to see everything:
npx shadcn@latest add --all --dry-run
Migrating Icon Libraries
Switch from one icon library to another:
npx shadcn@latest migrate icons
The migration scans your component files, identifies icon imports, and rewrites them to use the new library. Run with -y to skip confirmation:
npx shadcn@latest migrate icons -y
Migrating to the Radix UI Mono Package
Radix UI consolidated individual packages (e.g., @radix-ui/react-dialog, @radix-ui/react-popover) into a single radix-ui package. Migrate automatically:
npx shadcn@latest migrate radix
This updates all @radix-ui/react-* imports to use the mono package and cleans up your package.json.
Setting Up MCP for AI Coding Tools
Claude Code
npx shadcn@latest mcp init --client claude-code
Cursor
npx shadcn@latest mcp init --client cursor
VS Code
npx shadcn@latest mcp init --client vscode
Codex
npx shadcn@latest mcp init --client codex
OpenCode
npx shadcn@latest mcp init --client opencode
After initialization, your AI tool can use the MCP server to:
- Add components to your project via natural language
- Search the component registry
- Retrieve component documentation and usage examples
- Understand your project's shadcn/ui configuration
Viewing Component Docs from the Terminal
npx shadcn@latest docs dialog
This retrieves the full documentation for the component, including props, variants, and usage examples.
Updating a Component to the Latest Version
There is no dedicated update command. To update a component:
- Check what changed:
npx shadcn@latest add button --diff - If the changes look good, overwrite:
npx shadcn@latest add button --overwrite
Working in a Different Directory
All commands accept -c or --cwd to operate on a project in another directory:
npx shadcn@latest add button -c /path/to/other/project
npx shadcn@latest info -c /path/to/other/project
npx shadcn@latest init -c /path/to/new/project
Adding Components Through a Proxy
If your network requires a proxy for HTTPS connections:
https_proxy=http://proxy.company.com:8080 npx shadcn@latest add button
Using a Self-Hosted Registry
Point all CLI operations at your internal registry:
REGISTRY_URL=https://internal.company.com/r npx shadcn@latest add button
Or set it permanently in your shell profile:
export REGISTRY_URL=https://internal.company.com/r
Changing Base Colors
The four available base color palettes are:
| Color | Description |
|---|---|
neutral |
Clean, balanced grays |
zinc |
Cool-toned grays (default) |
stone |
Warm-toned grays |
mauve |
Purple-tinted grays |
Set during initialization when prompted, or edit components.json directly:
{
"tailwind": {
"baseColor": "stone"
}
}
Then reinstall components to apply the new color:
npx shadcn@latest init --reinstall
Using JavaScript Instead of TypeScript
During init, set TypeScript off. Or edit components.json:
{
"tsx": false
}
Components will be generated as .jsx files without type annotations.
Customizing Menu Appearance
Set menu styling in components.json:
{
"menuColor": "inverted",
"menuAccent": "bold"
}
menuColor Value |
Description |
|---|---|
default |
Standard menu colors |
inverted |
Inverted color scheme |
default-translucent |
Standard with transparency |
inverted-translucent |
Inverted with transparency |
menuAccent Value |
Description |
|---|---|
subtle |
Understated accent colors |
bold |
Prominent accent colors |
Batch Adding Components for a Dashboard
A typical dashboard needs several components. Add them all at once:
npx shadcn@latest add card table chart badge button input select tabs dialog dropdown-menu avatar separator -y
Setting Up a Component with Custom Alias Path
If your project uses a non-standard directory structure:
# Add to a custom path
npx shadcn@latest add button -p src/shared/ui
# Or update components.json to change the default
{
"aliases": {
"ui": "@/shared/ui"
}
}
Creating a Landing Page Component Set
For a marketing/landing page, a common component set:
npx shadcn@latest add button card badge separator accordion tabs -y
Creating an Admin Panel Component Set
For an admin panel or back-office:
npx shadcn@latest add table card button input label select checkbox dialog dropdown-menu sidebar navigation-menu badge avatar separator tabs command -y
6. Troubleshooting
Error: npm error Invalid Version
Cause: Node.js version is below the minimum requirement (v20).
Solution:
- Check your Node.js version:
node --version - Upgrade to Node.js v20 or later
- If using nvm:
nvm install 20 && nvm use 20
Prevention: Use a .nvmrc file in your project root with 20 to ensure the correct version.
(Related: GitHub issue #10377)
Error: Cannot find module '@/components/ui/button'
Cause: Path aliases are not configured in your bundler/TypeScript config, or the alias in components.json does not match your tsconfig.json paths.
Solution:
- Check
components.jsonaliases match yourtsconfig.jsonpaths:{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } - Restart your dev server after modifying
tsconfig.json - Run
npx shadcn@latest infoto verify alias resolution
Prevention: Let shadcn init configure aliases automatically rather than editing them manually.
Error: Installation failure when adding components
Cause: Network issues, registry unavailability, or incompatible Node.js version.
Solution:
- Check network connectivity:
curl https://ui.shadcn.com/r - Verify Node.js version:
node --version(must be v20+) - Clear npm cache:
npm cache clean --force - Try with a different package manager:
pnpm dlx shadcn@latest add button
Prevention: Ensure stable internet and correct Node.js version before running CLI commands.
(Related: GitHub issue #7129)
Error: Unable to download accordion with npx shadcn@latest add accordion
Cause: Registry fetch failure, often due to network restrictions, proxy requirements, or stale npm cache.
Solution:
- Clear npx cache:
npx clear-npx-cacheor delete~/.npm/_npx - Try specifying the registry URL explicitly:
REGISTRY_URL=https://ui.shadcn.com/r npx shadcn@latest add accordion - Check if a proxy is needed:
https_proxy=http://your-proxy:port npx shadcn@latest add accordion
Prevention: Configure https_proxy environment variable if behind a corporate firewall.
(Related: GitHub issue #5263)
Error: components.json not found
Cause: Running a command outside of an initialized shadcn/ui project, or the --cwd flag points to the wrong directory.
Solution:
- Run
npx shadcn@latest initto create the configuration file - If using
--cwd, verify the path:ls /path/to/project/components.json - Check you are in the correct directory:
pwd
Prevention: Always run commands from the project root, or use --cwd to specify the correct directory.
Error: Separator component renders incorrectly
Cause: Known issue with the separator component's default rendering.
Solution:
- After adding the separator component, inspect
components/ui/separator.tsx - Ensure Tailwind CSS classes are applied correctly
- Verify no CSS conflicts with other libraries in your project
- Check the component's orientation prop is set correctly (
"horizontal"or"vertical")
Prevention: Test components immediately after adding them.
(Related: GitHub issue #10415)
Error: Combobox loses selected value on parent re-render
Cause: The Combobox component's internal state resets when the parent component re-renders due to uncontrolled state management.
Solution:
- Lift the selected value state to the parent component
- Pass the value and onChange handler as controlled props
- Use
React.memooruseMemoto prevent unnecessary re-renders of the parent
(Related: GitHub issue #10414)
Error: CommandInput of Combobox inside Dialog not working
Cause: Focus management conflict between the Dialog and Command components. The Dialog traps focus, preventing the CommandInput from receiving keyboard events properly.
Solution:
- Use the
cmdklibrary's built-in Dialog variant:CommandDialog - Alternatively, set
shouldFilter={false}on the Command component and handle filtering manually - Add
onOpenAutoFocus={(e) => e.preventDefault()}toDialogContentif focus management is the issue
Prevention: When combining multiple compound components (Dialog + Command), test interaction behavior early.
(Related: GitHub issue #4516)
Error: CLI apply command does not work in monorepo
Cause: The apply command may not correctly resolve workspace roots in monorepo setups.
Solution:
- Run the command from the workspace root that contains
components.json - Use
--cwdto explicitly point to the correct workspace:npx shadcn@latest apply base-nova --cwd packages/ui - Ensure
components.jsonexists in the target workspace
(Related: GitHub issue #10411)
Error: @container/field-group not allowing div to grow
Cause: CSS container query scoping conflict where @container/field-group prevents child elements from expanding.
Solution:
- Check that your Tailwind CSS version supports container queries
- Verify the container name is correctly applied to the parent element
- Override the container styling in your component:
.field-group > div { flex-grow: 1; }
(Related: GitHub issue #9301)
Error: Animations not working with Tailwind v4
Cause: Tailwind CSS v4 changed how animations are configured. The tailwind.config.js animation definitions from v3 do not carry over.
Solution:
- For Tailwind v4, animations are defined in CSS rather than
tailwind.config.js - Check that your global CSS file includes the animation keyframes
- If migrating from Tailwind v3 to v4, move animation definitions from the config file to your global CSS
Prevention: When starting a new project with Tailwind v4, let shadcn init configure animations automatically.
(Related: GitHub issue #6536)
Error: React 19 hydration warning with dark mode script
Cause: React 19 emits a hydration warning when a <script> tag is used in the document body for dark mode initialization.
Solution:
- Move the dark mode script to
<head>using your framework's head management (e.g., Next.js<Script strategy="beforeInteractive">) - Use a theme provider library (e.g.,
next-themes) that handles script placement correctly - Add
suppressHydrationWarningto the<html>tag
(Related: GitHub issue #10104)
Components render unstyled or without Tailwind classes
Cause: Tailwind CSS is not scanning the component directory for classes, or the global CSS file is not imported.
Solution:
- For Tailwind v3, verify your config includes the component paths:
// tailwind.config.js content: [ "./src/components/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}", ] - For Tailwind v4, ensure your CSS
@sourcedirective covers the component paths - Confirm your global CSS file is imported in your app entry point (e.g.,
layout.tsx,main.tsx)
Prevention: Run npx shadcn@latest info after init to confirm Tailwind configuration paths are correct.
init fails with ENOENT: no such file or directory
Cause: The CLI cannot find or create the target directory structure.
Solution:
- Create the target directory manually:
mkdir -p my-project - Ensure you have write permissions to the parent directory
- On Windows, check for path length limitations and try a shorter path
Components have TypeScript errors after adding
Cause: Missing dependencies or incompatible TypeScript configuration.
Solution:
- Install all dependencies:
npm install - Check that
tsconfig.jsonincludes"jsx": "react-jsx"(or"preserve"for Next.js) - Ensure path aliases in
tsconfig.jsonmatchcomponents.json - Restart your TypeScript language server (in VS Code:
Ctrl+Shift+Pthen "TypeScript: Restart TS Server")
Styles look different from the shadcn/ui website previews
Cause: Different base color, missing CSS variables, or Tailwind configuration mismatch.
Solution:
- Compare your
components.jsonstyle and baseColor with the website defaults - Ensure
cssVariables: trueis set in your Tailwind configuration - Check that your global CSS file contains the full set of CSS custom properties generated during init
- Verify you are using the same style preset shown in the website preview
add --all takes very long or appears to hang
Cause: Downloading and installing 50+ components and their npm dependencies takes time.
Solution:
- Use
--dry-runfirst to verify the component list:npx shadcn@latest add --all --dry-run - Ensure stable internet connection
- Add components in batches instead:
npx shadcn@latest add button card dialog input label -y npx shadcn@latest add table tabs select textarea badge -y
Monorepo: components installed in wrong workspace
Cause: components.json aliases point to the wrong workspace package.
Solution:
- Check
components.jsonin your workspace root - Ensure the
aliases.uipath points to the correct workspace:{ "aliases": { "ui": "@repo/ui/components" } } - Run
npx shadcn@latest infoto verify workspace detection
Proxy/firewall blocks registry fetches
Cause: Corporate network requires HTTP proxy for external HTTPS connections.
Solution:
- Set the proxy environment variable:
export https_proxy=http://proxy.company.com:8080 npx shadcn@latest add button - For npm-specific proxy:
npm config set https-proxy http://proxy.company.com:8080
npx shadcn@latest runs an old cached version
Cause: npx caches previous versions of packages.
Solution:
- Clear the npx cache:
npx clear-npx-cache - The
@latesttag forces npm to check for the newest version, but the cache can still interfere. Clearing it resolves the issue.
Error: Could not resolve path aliases
Cause: The alias configuration in components.json does not match your project's path resolution setup.
Solution:
- For Next.js/TypeScript projects, ensure
tsconfig.jsonhas matching paths:{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } - For Vite, check
vite.config.tshas the resolve alias:import path from "path" export default defineConfig({ resolve: { alias: { "@": path.resolve(__dirname, "./src"), }, }, }) - Run
npx shadcn@latest initto reconfigure aliases from scratch
Components missing after init --reinstall
Cause: Reinstall only re-downloads components that are tracked internally. Manually added or renamed components may not be tracked.
Solution:
- Re-add specific components explicitly:
npx shadcn@latest add button dialog -o - Check which components the CLI tracks:
npx shadcn@latest info
Error: EPERM: operation not permitted on Windows
Cause: File locked by another process (IDE, dev server, antivirus).
Solution:
- Close your IDE and dev server
- Run the command again
- If using Windows Defender, add your project directory to the exclusion list
- Check for any file locks with Process Explorer or equivalent
CSS variables not applying in dark mode
Cause: The .dark class is not being toggled on the <html> element, or the dark mode CSS variables are missing from your stylesheet.
Solution:
- Verify your theme provider adds the
darkclass to<html>(not<body>) - Check your global CSS includes the
.darkselector with variable overrides - For Next.js with
next-themes, ensureattribute="class"is set on theThemeProvider
Diff shows no changes but component behaves differently
Cause: Component behavior changes may come from updated dependencies (Radix UI, Tailwind CSS) rather than component source code changes.
Solution:
- Check your
package.jsonfor dependency version changes - Compare current Radix UI / Base UI versions with what the component was built against
- Update dependencies:
npm update - Check the registry for any changelogs or migration notes
Error: ECONNREFUSED or ETIMEDOUT when fetching components
Cause: Cannot connect to the registry server. Network issue, DNS resolution failure, or the registry is temporarily down.
Solution:
- Check if the registry is accessible:
curl -I https://ui.shadcn.com/r - Try a different DNS resolver (e.g.,
8.8.8.8) - If behind a VPN, try disconnecting and reconnecting
- Wait a few minutes and retry — the registry may be experiencing temporary issues
Components have peer dependency warnings
Cause: Your project's React or Tailwind version does not match the expected range for a component's dependencies.
Solution:
- Check the warnings for specific version requirements
- Update your React version:
npm install react@latest react-dom@latest - Use
--legacy-peer-depsif you need to force installation (npm only):npm install --legacy-peer-deps
7. FAQ
Q: Is shadcn/ui a component library?
No. shadcn/ui is a CLI tool and component registry. Instead of installing a library as a dependency, the CLI copies component source code directly into your project. You own the code and can modify it freely. There is no shadcn-ui package in your node_modules.
Q: Do I need to install shadcn/ui as a dependency?
No. You run the CLI using npx shadcn@latest (or your package manager's equivalent). The CLI itself is not added to your project's package.json. Only the components' runtime dependencies (like Radix UI primitives, class-variance-authority, clsx) are installed as project dependencies.
Q: What is the difference between Radix UI and Base UI?
Radix UI (from WorkOS) and Base UI (from MUI) are both unstyled, accessible component primitive libraries. shadcn/ui supports both as the underlying foundation for its components. Radix is the default and has broader community adoption. Choose Base UI if you prefer MUI's approach or already use MUI in your project. Select your base with --base radix or --base base during init.
Q: Can I use shadcn/ui with JavaScript (not TypeScript)?
Yes. Set "tsx": false in your components.json or choose JavaScript during init. Components will be generated as .jsx files without type annotations.
Q: How do I update a component to the latest version?
Run npx shadcn@latest add <component> --overwrite. There is no dedicated update command. Use --diff first to review what changed before overwriting.
Q: Will updating a component overwrite my customizations?
Yes. The --overwrite flag replaces the entire component file with the latest version from the registry. Commit your customizations before updating, then use --diff to see what changed so you can re-apply your modifications afterward.
Q: Can I use shadcn/ui with Tailwind CSS v3?
Yes. The CLI supports both Tailwind CSS v3 and v4. The init command detects your Tailwind version and configures accordingly. Be aware that animation configuration differs between v3 (config file) and v4 (CSS).
Q: What frameworks does shadcn/ui support?
Six frameworks have built-in templates: Next.js, Vite (React), React Router, TanStack Start, Astro, and Laravel. Other React-based frameworks may work with manual configuration of components.json.
Q: Can I use shadcn/ui in a monorepo?
Yes. Use npx shadcn@latest init --monorepo to scaffold a monorepo setup. The CLI distributes components, hooks, and utilities to the correct workspace packages. For existing monorepos, ensure components.json is in the workspace root with correct alias paths.
Q: How do I add dark mode support?
Dark mode works through Tailwind CSS's dark: variant and CSS custom properties. Ensure cssVariables: true in components.json, and use a theme provider (like next-themes for Next.js) to toggle the dark class on the <html> element. The CSS variables for dark mode are generated automatically during init.
Q: What is components.json?
It is the configuration file for shadcn/ui, created at your project root during init. It tells the CLI your style preferences, file paths, import aliases, icon library, RTL settings, and registry configuration. The CLI reads this file for every operation.
Q: Can I use a custom component registry?
Yes. Define custom registries in the registries field of components.json using a URL template with {name} and {style} placeholders. Then add components with npx shadcn@latest add <registry-name>/<component>.
Q: How do I build and host my own registry?
Create a registry.json file defining your components (with types like registry:ui, registry:hook, registry:lib, registry:theme, registry:style, registry:base, registry:font), run npx shadcn@latest build to compile it, and host the output directory on any static file server.
Q: What is the MCP server for?
The MCP (Model Context Protocol) server allows AI coding tools like Claude Code, Cursor, VS Code, Codex, and OpenCode to interact with shadcn/ui programmatically. The AI can add components, search the registry, and read documentation through the MCP interface. Initialize with npx shadcn@latest mcp init --client <client-name>.
Q: What does shadcn init --defaults do?
It initializes a project with --template=next and --preset=base-nova, skipping all interactive prompts. This is the fastest way to start a new project with sensible defaults.
Q: What is the apply command for?
The apply command applies a preset configuration to an existing project. Presets bundle a style, theme, and component configuration. Use it to change the visual identity of your project without re-initializing from scratch.
Q: How do I set up RTL (right-to-left) layouts?
Either initialize with --rtl or run the migration on an existing project: npx shadcn@latest migrate rtl. The migration transforms component files to use logical CSS properties (e.g., margin-inline-start instead of margin-left).
Q: What does migrate radix do?
It migrates your imports from individual @radix-ui/react-* packages to the consolidated radix-ui mono package. This simplifies your dependency tree and aligns with Radix UI's current distribution model.
Q: Can I use shadcn/ui without React Server Components?
Yes. Set "rsc": false in components.json. This is the default for non-Next.js frameworks (Vite, React Router, etc.) that do not support RSC. Components will include "use client" directives where needed.
Q: Where are components installed by default?
Components go to the path defined by aliases.ui in components.json (typically @/components/ui, which resolves to src/components/ui/). You can override this per-command with the --path flag.
Q: Can I add components from a URL?
Yes. Pass a full URL to a registry JSON file: npx shadcn@latest add https://example.com/r/styles/new-york-v4/button.json. This works with any URL that serves a valid component registry JSON.
Q: How do I preview what add will do without making changes?
Use --dry-run: npx shadcn@latest add dialog --dry-run. This shows what files would be created and what dependencies would be installed, without writing anything to disk.
Q: What is the REGISTRY_URL environment variable?
It overrides the default registry URL (https://ui.shadcn.com/r). Set it to point at a self-hosted or custom registry for all CLI operations. Useful for air-gapped environments or internal component libraries.
Q: How do I check which components are installed?
Run npx shadcn@latest info to see your project configuration. You can also inspect the files in your UI directory (typically src/components/ui/) directly.
Q: What happens if I run add for a component that already exists?
The CLI prompts you for confirmation before overwriting. To overwrite without prompting, use --overwrite (-o). Without that flag, existing files are preserved and the command exits without changes.
Q: Can I use shadcn/ui with a Tailwind prefix?
Yes. Set "prefix" in components.json under the tailwind field (e.g., "prefix": "tw-"). All generated Tailwind classes will include the prefix, avoiding collisions with other CSS frameworks.
Q: Which icon library does shadcn/ui use by default?
Lucide, configured via "iconLibrary": "lucide" in components.json. You can migrate to a different icon library using npx shadcn@latest migrate icons.
Q: What is the diff command?
The standalone diff command is deprecated. Use npx shadcn@latest add <component> --diff instead to see what has changed between your local version and the registry version of a component.
Q: What base colors are available?
Four base color palettes: neutral (balanced grays), zinc (cool grays, the default), stone (warm grays), and mauve (purple-tinted grays). Set via tailwind.baseColor in components.json.
Q: How does the search command work?
npx shadcn@latest search <registry> -q <query> searches a registry for components matching your query. The list alias works identically. Use -l to limit results and -o to paginate.
Q: Can I use shadcn/ui with Astro?
Yes. Use npx shadcn@latest init -t astro to scaffold an Astro project with React islands. Components are added the same way as any other framework — npx shadcn@latest add button.