Subchapter 5.9
resources/setup-guide.mdMarkdown10 KBView on GitHub
This guide walks you through setting up shadcn/ui in both new and existing projects.
Before you begin, ensure you have:
The easiest way to start a new project with shadcn/ui is using the create command, which allows you to customize everything (framework, library, style, font, etc.).
npx shadcn@latest createThis interactive command will guide you through:
# Create a new Next.js project
npx create-next-app@latest my-app
cd my-app
# Initialize shadcn/ui
npx shadcn@latest init
# Add your first component
npx shadcn@latest add button# Create a new Vite project
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
# Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
# Initialize shadcn/ui
npx shadcn@latest init
# Add your first component
npx shadcn@latest add buttonIf Tailwind is not installed:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pConfigure tailwind.config.js:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}Run the initialization command:
npx shadcn@latest initYou’ll be asked to configure:
Style: Choose between default, new-york, or one of the new styles (Vega, Nova, etc.)
default: Clean and minimal designnew-york: More refined with subtle detailsBase Color: Choose your primary color palette
CSS Variables: Recommend yes for easier theming
TypeScript: Recommend yes for type safety
Import Alias: Default is @/components (recommended)
React Server Components: Choose based on your framework
yes for Next.js 13+ with app directoryno for Vite, CRA, or Next.js pages directoryRTL Support: Answer yes if you need Right-to-Left layout support (this will use logical properties like ms-4 instead of ml-4).
shadcn/ui now offers multiple visual styles beyond the defaults:
You can now choose between Radix UI and Base UI as the underlying primitive library. They share the same component API/abstraction, so your usage remains consistent.
The init command creates/updates several files:
components.json (root of project):
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib"
}
}src/lib/utils.ts:
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}Updated tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{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))",
},
// ... more colors
},
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")],
}Updated globals.css (or equivalent):
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... dark mode variables */
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}Ensure your tsconfig.json includes path aliases:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}For Vite, also update vite.config.ts:
import path from "path"
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})Now you can add components:
# Add individual components
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add dialog
# Add multiple components at once
npx shadcn@latest add button card dialog input labelComponents will be added to src/components/ui/ by default.
rsc: true in components.json"use client" to stateful componentsrsc: false in components.jsonvite.config.tsglobals.css in your main entry point (main.tsx)craco or react-app-rewired for path alias supportCheck file structure:
src/
├── components/
│ └── ui/
├── lib/
│ └── utils.ts
└── index.css (or globals.css)Test a simple component:
import { Button } from "@/components/ui/button"
export default function App() {
return <Button>Click me</Button>
}Verify Tailwind is working:
Test dark mode (if using CSS variables):
<html className="dark">Solution: Check path alias configuration in tsconfig.json and framework config.
Solution:
globals.css is imported in your app entry pointcontent paths include your filesglobals.cssSolution:
npm install to ensure all dependencies are installed@types/react is installedSolution:
tailwindcss-animate is installed: npm install tailwindcss-animate/examplesSource