shadcn/ui
risingA collection of beautifully designed, accessible components you copy into your project. Not a dependency — you own every line of code.
Quick Verdict
shadcn/ui is the best starting point for React UI in 2026. Production-quality components, zero lock-in — every component lives in your codebase, fully customizable. AI tools like Cursor and Claude generate shadcn code more reliably than any other component library.
When to use it: Any React/Next.js project that needs UI components. The copy-paste model is a feature, not a limitation.
When not to: You need specialized widgets (data grids, complex date pickers, rich text editors) — shadcn covers fundamentals, not everything.
Best For
- Next.js App Router — most components work as server components out of the box
- AI-assisted development — consistent patterns, well-documented, heavily indexed in LLM training data
- Teams that want code ownership — modify any component without fighting upstream abstractions
- Dark mode / theming — CSS custom properties + Tailwind tokens make theming straightforward
Avoid If
- You need a comprehensive widget library beyond the fundamentals
- Your team refuses to use Tailwind — the components are Tailwind-native
- You need strict Material Design or Ant Design compliance
Why the Copy-Paste Model Wins
Traditional component libraries create dependency lock-in. You can't change component internals without forking, you wait for upstream PRs, and major version upgrades can break your UI.
shadcn flipped this: npx shadcn add button copies the button component into your src/components/ui/ directory. You own it. You modify it. You break it if you want. No upstream dependency, no version constraint.
The v4 release moved from Radix to Base UI primitives and introduced cleaner styling. The CLI remains the same — one command per component.
Hidden Costs
Zero. No subscription, no licensing, no npm package to pay for. The only cost is reading and understanding the components you modify — which you should do anyway since you own them.
Correct vs Cargo-Culted Patterns
Wrong — importing like a package:
// ❌ This doesn't exist
import { Button } from 'shadcn-ui'Right — from your own components directory:
// ✅ You own this file after running npx shadcn add button
import { Button } from '@/components/ui/button'Wrong — hardcoded variants instead of cn():
// ❌ Class conflicts, hard to maintain
<button className={`px-4 py-2 ${variant === 'outline' ? 'border border-input' : 'bg-primary'}`}>Right — cn() for conditional variants:
// ✅ tailwind-merge resolves conflicts, readable
<button className={cn(
'px-4 py-2 rounded-md',
variant === 'outline' && 'border border-input bg-transparent',
variant === 'default' && 'bg-primary text-primary-foreground',
)}>Wrong — ignoring theme config:
// ❌ Hardcoded color defeats the theming system
<div className="bg-[#1a1a2e] text-[#ffffff]">Right — CSS custom properties via theme:
/* globals.css — define once, use everywhere */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
}
}AI Coding Notes
Always specify your shadcn version (v3 Radix vs v4 Base UI — different component internals). Tell the AI:
- "Using shadcn/ui v4 with Base UI"
- "Use
cn()from@/lib/utilsfor conditional classes" - "Components are in
src/components/ui/"
Provide the component file as context when asking for modifications — AI produces better changes when it can see the actual source.
Common AI Mistakes
- Importing from npm package — shadcn is not a dependency. Components are in your
src/components/ui/directory. - v3 patterns in v4 project — v4 uses Base UI instead of Radix,
@theme inlineinstead oftailwind.config.ts - Fighting Tailwind — shadcn and Tailwind are inseparable. If you need CSS Modules, use a different library.
- Not customizing via CSS variables — hardcoding colors instead of using the theme token system.
- Using v4 CLI to add v3 components — always run
npx shadcn addwith the correct version.
Start With / Grow Into / Avoid Until Needed
Start with shadcn for any React/Next.js project that needs UI components. The CLI makes it fast.
Grow into the theme system once your design tokens are defined — CSS custom properties + @theme create a maintainable design system.
Avoid until needed: Custom component wrapping layers, design system packages on top of shadcn — start lean.
Migration Implications
Low pain. You own the component files — they're just TypeScript + Tailwind. Migrating to a different component library means rewriting UI, not a library upgrade.