The copied-source model has one cost and this is it: when the upstream component gets a fix, nothing tells you. There is no version, no changelog entry against your dependency, no alert. The component in your repository is exactly as good as the day you installed it.
That is a manageable cost, and the way to manage it is not to check constantly.
What actually changes upstream
Worth being specific, because the fear is larger than the reality. Primitive components are stable: a button, a card and a dialog have not meaningfully changed in a long time. What does change is the layer underneath - the primitive library's accessibility fixes, a Tailwind version's syntax, a React version's behaviour - and those arrive through your package manager, not through the component.
So the practical answer is that most of your copied components never need updating, and the few that do are the ones wrapping something that moved.
The three occasions to look
A framework or primitive major version. When Radix, Base UI or Tailwind ships a major, the components that wrap it are the ones to check. That is a handful, not all of them.
A reported bug. Someone finds a focus trap that does not trap. Check whether upstream fixed it, take the fix, and note it.
A deliberate audit, once or twice a year. Not a diff of everything: a pass over the components that carry behaviour - dialog, select, combobox, table - against the current upstream version.
Between those, leave them alone. A component that works and is not blocking anything is not technical debt.
How to actually diff
You have the file; upstream has a file. The cheapest reliable method is to install the current upstream version into a scratch directory and compare:
The diff tells you two things at once: what upstream changed, and what you changed. The second half is usually the more valuable, because in a year nobody remembers which edits were deliberate.
Never run add --overwrite on a component you have edited and then try to recover. Commit first, overwrite, then reapply your changes on top with the diff in front of you.
Making future-you faster
Three conventions cost nothing now and save the audit later.
Comment the edits. One line at the top of any component you changed, saying what and why. This is the single highest-value habit in this whole article, because it converts an archaeological question into a readable one.
Keep the component recognisable. A minimally edited component can be re-derived from a new upstream version. A rewritten one is yours forever, which is fine if that was the intent and expensive if it was not.
Read the diff on every add. The CLI guide makes the same point from the other direction: it is how you notice a second registry overwriting the first.
The registries you do not control
An installed component from a community registry has the same property, with one difference: the upstream may disappear or rename, so the install command in your README may stop working even though your copy is fine.
The mitigation is not to pin anything - you cannot - but to know which of your components came from where. A comment with the source URL at the top of the file is enough, and it is what makes the annual pass possible at all.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
A scratch install plus diff | Seeing upstream's change and yours at once | Manual, and only when you remember |
| An npm package | Fixes arriving automatically with a version bump | You cannot edit the component |
| Your own git history | Knowing what you changed, if the commits are clean | Only as good as the commit messages |
| 21st | Replacing a component whose upstream went quiet | Quality varies by author, so preview before you take it |
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.
Frequently asked
- How do you update a component you copied into your repo?
- Install the current upstream version into a scratch directory and diff it against yours. The diff shows both what upstream changed and what you changed, and the second half is usually more valuable, because in a year nobody remembers which edits were deliberate.
- How often should copied components be updated?
- Rarely. Primitives are stable; what moves is the layer underneath, which arrives through your package manager. Look on three occasions: a major version of a primitive library or Tailwind, a reported bug, and one deliberate audit a year over the components that carry behaviour.
- Is it safe to run add --overwrite on an edited component?
- Only with a clean working tree. Overwrite replaces the file and your edits with it. Commit first, overwrite, then reapply your changes with the diff in front of you, which is also the moment to write down what the edits were for.
- What if a community registry disappears?
- Your copy keeps working, because add copied the source rather than linking to it. What breaks is the install command in your README, and any future install. Keeping a comment with the source URL at the top of the file is what makes an audit possible later.



