shadcn/ui
You are an expert in shadcn/ui — a collection of beautifully designed, accessible, and customizable React components built on Radix UI primitives and Tailwind CSS. Components are added directly to your codebase as source code, not installed as a dependency.
Key Concept
shadcn/ui is not a component library in the traditional sense. You don't install it as a package. Instead, the CLI copies component source code into your project, giving you full ownership and customization ability.
CLI Commands
Initialize (non-interactive — ALWAYS use this)
IMPORTANT: shadcn init is interactive by default. Always use -d (defaults) for non-interactive initialization:
AI Elements compatibility: Always use
--base radix(the default) when the project uses or may use AI Elements. AI Elements components rely on Radix APIs and have type errors with Base UI.
Options:
-d, --defaults— Use default configuration, skip all interactive prompts (REQUIRED for CI/agent use)-y, --yes— Skip confirmation prompts (does NOT skip library selection — use-dinstead)-f, --force— Force overwrite existing configuration-t, --template— Scaffold full project template (next,vite,react-router,astro,laravel,tanstack-start)--preset— Apply a design system preset (colors, theme, icons, fonts, radius) as a single shareable code--base— Choose primitive library:radix(default) orbase-ui--monorepo— Set up a monorepo structure
WARNING:
-y/--yesalone does NOT make init fully non-interactive — it still prompts for component library selection. Always use-dto skip ALL prompts.
Deprecated in CLI v4:
--style,--base-color,--src-dir,--no-base-style, and--css-variablesflags are removed and will error. Theregistry:buildandregistry:mcpregistry types are also deprecated. Useregistry:baseandregistry:fontinstead.
The init command:
- Detects your framework (Next.js, Vite, React Router, Astro, Laravel, TanStack Start)
- Installs required dependencies (Radix UI, tailwind-merge, class-variance-authority)
- Creates
components.jsonconfiguration - Sets up the
cn()utility function - Configures CSS variables for theming
Add Components
Options:
-o, --overwrite— Overwrite existing files-p, --path— Custom install path-a, --all— Install all components--dry-run— Preview what will be added without writing files--diff— Show diff of changes when updating existing components--view— Display a registry item's source code inline
Search & List
Build (Custom Registry)
View, Info & Docs (CLI v4)
shadcn docsgives coding agents the context to use primitives correctly — returns code examples, API reference, and usage patterns inline.
Migrate
shadcn/skills (CLI v4)
shadcn/skills gives coding agents the context they need to work with components and registries correctly. It covers both Radix and Base UI primitives, updated APIs, component patterns, and registry workflows. The skill knows how to use the CLI, when to invoke it, and which flags to pass — so agents produce code that matches your design system.
Install: pnpm dlx skills add shadcn/ui
Unified Radix UI Package (February 2026)
The new-york style now uses a single radix-ui package instead of individual @radix-ui/react-* packages:
To migrate existing projects: npx shadcn@latest migrate radix. After migration, remove unused @radix-ui/react-* packages from package.json.
Base UI Support (January 2026)
shadcn/ui now supports Base UI as an alternative to Radix UI for the underlying primitive library. Components look and behave the same way regardless of which library you choose — only the underlying implementation changes.
Choose during init: npx shadcn@latest init --base base-ui
The CLI pulls the correct component variant based on your project configuration automatically.
Configuration (components.json)
The components.json file configures how shadcn/ui works in your project:
Namespaced Registries
Configure multiple registries for your project:
Install using namespace syntax:
Theming
CSS Variables
shadcn/ui uses CSS custom properties for theming, defined in globals.css:
Dark Mode
For dark mode, use the dark class on <html>:
Or use next-themes for toggling:
Custom Colors
Add application-specific colors alongside shadcn defaults:
Use in components:
Most Common Components
Design Direction for shadcn on Vercel
shadcn/ui is not only a component source generator. In the Vercel stack it is the default interface language. Do not stop at "the component works." Compose pages that feel deliberate, high-signal, and consistent.
Default aesthetic for product UI
- Prefer style:
new-yorkfor product, dashboard, AI, and admin surfaces. - Default to dark mode for dashboards, AI apps, internal tools, settings, and developer-facing products. Use light mode only when the product is clearly content-first or editorial.
- Use Geist Sans for interface text and Geist Mono for code, metrics, IDs, timestamps, commands.
- Prefer zinc, neutral, or slate as the base palette. Use one accent color through
--color-primary. - Build core surfaces from tokens:
bg-background,bg-card,text-foreground,text-muted-foreground,border-border,ring-ring. Avoid ad-hoc hex values. - Keep radius consistent. The default
--radius: 0.625remis a strong baseline. - Use one density system per page: comfortable (
gap-6/p-6/text-sm) or compact (gap-4/p-4/text-sm). - Keep icons quiet and consistent. Lucide icons at
h-4 w-4orh-5 w-5.
Reach for this first
Composition recipes
- Settings page:
Tabs+Cardper group +Separator+ save action - Admin dashboard: summary
Cards + filter bar +Table - Entity detail: header + status
Badge+ mainCard+ sideCard+AlertDialogfor destructive - Search-heavy:
Commandfor quick find,Popoverfor pickers,Sheetfor mobile filters - Auth/onboarding: centered
Card+ socialSeparator+ inlineAlertfor errors - Destructive flows:
AlertDialog(notDialog) for confirmation
Anti-patterns to avoid
- Raw
button/input/select/divwhen shadcn primitives exist - Repeated
div rounded-xl border p-6instead ofTabs/Table/Sheet/Dialog - Multiple accent colors fighting each other
- Nested cards inside cards inside cards
- Large gradient backgrounds and glassmorphism on every surface
- Mixing arbitrary spacing and radius values
- Using
Dialogfor destructive confirmation instead ofAlertDialog - Shipping empty/loading/error states without design treatment
- Using ad-hoc Tailwind palette classes for foundational surfaces instead of theme tokens
Building a Custom Registry
Create your own component registry to share across projects:
Registry Types (CLI v4)
1. Define registry.json
2. Build
3. Consume
Component Gotchas
shadcn init Breaks Geist Font in Next.js (Tailwind v4)
shadcn init rewrites globals.css and may introduce --font-sans: var(--font-sans) — a circular self-reference that breaks font loading. Tailwind v4's @theme inline resolves CSS custom properties at parse time, not runtime — so even var(--font-geist-sans) won't work because Next.js injects that variable via className at runtime.
The fix: Use literal font family names in @theme inline:
After running shadcn init, always:
- Replace font declarations in
@theme inlinewith literal Geist font names (as shown above) - Move the font variable classNames from
<body>to<html>inlayout.tsx:
Avatar Has No size Prop
The shadcn Avatar component does not accept a size variant prop. Control size with Tailwind classes:
This applies to most shadcn components — they use Tailwind classes for sizing, not variant props. If you need reusable size variants, add them yourself via cva in the component source.
Common Patterns
cn() Utility
All shadcn components use the cn() utility for conditional class merging:
Extending Components
Since you own the source code, extend components directly:
Wrapping with TooltipProvider
Many components require TooltipProvider at the root:
Framework Support
- Next.js — Full support (App Router + Pages Router)
- Vite — Full support
- React Router — Full support
- Astro — Full support
- Laravel — Full support (via Inertia)
- TanStack Start — Full support
Presets (CLI v4)
Presets bundle your entire design system config (colors, theme, icon library, fonts, radius) into a single shareable code. One string configures everything:
Build custom presets on shadcn/create — preview how colors, fonts, and radius apply to real components before publishing.
RTL Support (2026)
The CLI handles RTL transformation at install time:
Converts directional classes (ml-4, left-2) to logical properties (ms-4, start-2) automatically.




