What Is shadcn/ui and How Does Its Copy-In Component Model Work?
Updated
shadcn/ui is a collection of React components built on Tailwind CSS that you copy into your own project instead of installing as a package. You get the source files, own them, and edit them freely. Use it when you want full control over component markup and styling in a React + Tailwind codebase; skip it if you need a versioned dependency with centralized updates.
The copy-in model, explained
A traditional component library ships as an npm package. You import a component, and its internals stay hidden in node_modules. Upgrading means bumping a version number.
shadcn/ui works differently. A CLI writes the component's source code directly into your project, typically under a components/ui folder. From that moment it is your code:
- You can change class names, markup, and behavior.
- There is no package version to upgrade; updates are something you apply yourself.
- Nothing breaks if the upstream project changes, because you are no longer linked to it.
The tradeoff is symmetrical: maximum customization freedom, but you take on maintenance. If a component has a bug or an accessibility fix lands upstream, you won't receive it automatically.
How setup typically works
The exact commands and prompts depend on your project setup, but the flow follows a consistent pattern:
- Prerequisites. A React project with Tailwind CSS configured, plus path aliases (for example
@/components) so the CLI knows where to place files. - Initialize. Run the shadcn CLI init command. It detects your framework and Tailwind setup, creates a config file, and sets up a utility for merging class names.
- Add components. Run the add command for a specific component. The CLI fetches the source and writes it into your components directory, along with any dependencies it needs.
- Verify. Import the component in a page and render it. If styles look wrong, the usual culprits are a missing Tailwind content path or a misconfigured alias.
Common sticking points
- Aliases not resolving. The CLI relies on your
tsconfigor bundler alias config. A mismatch causes files to land in the wrong place or imports to fail. - Tailwind not scanning the new folder. Components render unstyled until your Tailwind content globs include the directory.
- Expecting automatic updates. There is no upgrade path. Treat copied components as forked code you now own.
How it differs from an npm component library
| Dimension | shadcn/ui (copy-in) | npm component library |
|---|---|---|
| Ownership | You own and edit the source | Package internals are hidden |
| Updates | Manual; you merge changes yourself | Version bump |
| Customization | Unlimited | Limited to exposed props and theme hooks |
| Bundle control | You see and prune every file | Depends on package internals |
| Best for | Teams wanting bespoke design systems | Teams wanting low-maintenance consistency |
Choose copy-in when your design diverges from defaults and you want to own the code. Choose a packaged library when consistency and easy upgrades matter more than deep customization.
Blocks and registries extend the model
Beyond single components, the ecosystem offers blocks: larger prebuilt sections such as dashboards, pricing tables, or authentication screens composed from shadcn/ui primitives. Creative Tim, for instance, lists 360+ shadcn/ui blocks aimed at AI code generators like v0 and Lovable, delivered with a registry and MCP support. Registries let a CLI pull components and blocks from a hosted source rather than only the default set, so you can scaffold whole pages instead of assembling primitives one at a time.
This matters for speed: you still end up owning the copied code, but you start from a working layout rather than an empty file.
Deciding whether to use it
Use shadcn/ui if you are on React with Tailwind, want accessible defaults you can modify, and are comfortable owning component code. Look elsewhere if you need guaranteed upstream fixes, work outside React/Tailwind, or prefer a stable dependency contract over editable source.