Vercel Logo

One of the most important aspects of owning your component code is understanding how to maintain it over time. Unlike traditional npm packages that update automatically, shadcn/ui components become part of your codebase, which means you need strategies for updates, maintenance, and evolution. Let's explore how to keep your components healthy and current.

The Ownership Model: Benefits and Responsibilities

When you copy shadcn/ui components into your project, you gain complete ownership, but with that comes responsibility:

What You Gain

  • Complete control over component behavior and styling
  • No breaking changes from external updates
  • Custom modifications that persist over time
  • Project-specific optimizations

What You Own

  • Security updates for component dependencies
  • Bug fixes and improvements
  • Feature additions and enhancements
  • Breaking change management

Understanding this balance is crucial for long-term success with shadcn/ui.

Ownership vs. Maintenance

The copy-paste model means you control when and how components change, but you're also responsible for keeping them secure, functional, and up-to-date. This trade-off gives you stability and control at the cost of automatic updates.

Proxying components

One way of customize shadcn/ui components without overwriting them is to proxy them - re-exporting or pre-composing them with your own code. This makes the components much easier to update, however it effectively doubles the component design system size and makes the ownership concept redundant.

A pre-composed / proxied component might look like this:

Reacttooltip.tsx
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';

type MyTooltipProps = {
  text: string;
  children: ReactNode;
}

export const MyTooltip = ({ text }: MyTooltipProps) => (
  <Tooltip>
    <TooltipTrigger>
      {children}
    </TooltipTrigger>
    <TooltipContent className="bg-black text-white">
      <p>{text}</p>
    </TooltipContent>
  </Tooltip>
)

Since this component doesn't directly overwrite the original tooltip.tsx, we can update the component like so:

npx shadcn@latest add tooltip --overwrite

Or, to update all components:

npx shadcn@latest add --all --overwrite

Overwriting components

The most common way to customize shadcn/ui components is to install the files and overwrite them directly as intended. This breaks upstream updates, however you can use the shadcn/ui diff command to compare your components with the latest versions:

# Check if a specific component has updates
npx shadcn@latest diff button

# Check all components
npx shadcn@latest diff

Then, you'll need to apply the new updates manually.

Question
What is the recommended approach when shadcn/ui releases an update to a component you've heavily customized?

In our next lesson, we'll explore the globals.css file that powers shadcn/ui's theming system and learn how CSS variables create a flexible, maintainable design language.