The difference between a component you install and a snippet you paste is not convenience. It is that one of them declares what it needs and the other does not, and that single property decides whether a project with forty borrowed components is maintainable or a mystery.
What a copy button does not do
A snippet from a documentation page arrives with no record of where it came from, no list of the packages it imports, and no relationship to the primitives it assumes you already have. Three consequences follow, and all three show up later rather than immediately.
The build fails on an import you do not have, with nothing to tell you which package it wanted or which version.
Nothing knows the component exists. No inventory, no audit, no way to answer "where did this come from" in a year.
The pasted markup carries the source's colours, so it looks right in the documentation screenshot and wrong in your theme, and it will never follow a theme change. The compatibility test is how to spot that before pasting.
What a CLI install does
npx shadcn add <url> reads the item's manifest, installs the npm packages it declares, resolves the other registry items it needs, and writes files into the paths your components.json defines with the imports rewritten to match. The CLI guide has the four steps in full.
The valuable part is the manifest. An item that declares its dependencies can be installed into a clean project by someone who has never seen it, which is exactly what a snippet cannot promise.
What it still does not do
Worth being honest, because the model has real edges.
There is no version, so nothing tells you when upstream fixes something, which the maintenance guide covers. Two registries can overwrite each other's button.tsx. And the CLI resolves dependencies but does not judge them: an item that pulls an animation runtime for one transition installs cleanly and costs you the runtime.
Those are all visible in the diff, which is why reading it after every install is the habit that makes the model safe.
Choosing sources on this basis
Prefer registries that publish an index, because that is what makes the CLI path available at all. The directory lists the ones that do, with their size, stars and last commit.
For a source that only offers copy-paste, the honest approach is to treat it as a reference implementation: read it, understand the technique, and write the component into your own system rather than pasting markup that carries someone else's tokens.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| The registry directory | Sources that install through a CLI with dependencies declared | Only registries that publish an index |
| 21st MCP | The same installs from the editor, with previews first | Installs need a membership |
| Copy-paste galleries | One component, quickly, from anywhere | Nothing declared, nothing tracked |
| An npm package | Real versions and automatic fixes | You cannot edit the component |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue.
Browse the registry directory →
Frequently asked
- Why prefer a CLI install over copying a snippet?
- Because the item declares its dependencies. A pasted snippet fails the build on an import you do not have, with nothing to say which package it wanted; leaves no record of where the component came from; and carries the source's own colours rather than reading your tokens.
- What does a registry install actually resolve?
- The npm packages the item declares, the other registry items it depends on, recursively, and the file paths your components.json aliases define, with imports rewritten to match. That is what makes a component installable into a clean project by someone who has never seen it.
- What does the CLI model still not solve?
- There is no version, so nothing tells you when upstream fixes something; two registries can overwrite each other's button; and the CLI resolves dependencies without judging them, so an item that pulls an animation runtime for one transition installs cleanly. All three are visible in the diff.
- What if a source only offers copy-paste?
- Treat it as a reference implementation. Read it, understand the technique, and write the component into your own system rather than pasting markup that carries someone else's tokens and declares nothing about what it needs.



