Skip to content

Frontend

shadcn/ui Made Component Ownership Practical.

Open code. Clear responsibility.

Aidxn
Written by Aiden Wood Founder and Lead Design Engineer
From registry to maintained component A registry item enters your project as source code. Your team then owns its variants, accessibility, tests, and any later upstream comparison. SOURCEdata in DECIDElogic RESULTaction out

From registry to maintained component

A registry item enters your project as source code. Your team then owns its variants, accessibility, tests, and any later upstream comparison.

Browse Velocity Components

shadcn/ui is not a traditional component package. It is a code distribution system. You add a component, read its source in your own project, then take responsibility for what happens next.

That distinction matters when your interface has to look and behave like your product. You can change markup, motion, tokens, and behaviour without waiting for a library API to expose the right prop. You also own upgrades, tests, and accessibility regression checks. Freedom is not free. It is useful when you choose it deliberately.

What the CLI gives you

The current shadcn CLI can initialise a project, add named components, and resolve registry dependencies. Its components.json file records aliases, styling choices, and registry configuration. It is a delivery mechanism for source, not a promise that every copied component will stay updated for you.

pnpm dlx shadcn@latest init
pnpm dlx shadcn@latest add button dialog

Before accepting generated source, inspect the component and its dependencies. Check that its keyboard behaviour, focus management, and visual tokens match your product. Then commit the result as code you maintain.

When open code earns its keep

  • Your product needs branded variants that a package theme cannot express cleanly.
  • A component is shared across pages and needs one intentional API.
  • You need to debug, test, or change the markup without a wrapper layer.
  • Your team has capacity to own upgrades and security fixes.

It is less compelling for one page experiments or teams without time to maintain the source they import. In those cases, a small native component or a well maintained package can be the calmer decision.

Make ownership visible in code

A copied button should not become untouchable vendor code. Give it a small API and test the states customers can actually reach: disabled, loading, long labels, keyboard focus, and narrow screens.

type ActionButtonProps = {
  children: React.ReactNode;
  pending?: boolean;
} & React.ComponentProps<'button'>;

export function ActionButton({
  children,
  pending = false,
  disabled,
  ...props
}: ActionButtonProps) {
  return (
    <button
      {...props}
      disabled={disabled || pending}
      aria-busy={pending || undefined}
    >
      {pending ? 'Sending' : children}
    </button>
  );
}

This is intentionally boring. A clear component contract makes the design system easier to change than an unexamined pile of copied files.

Use source ownership to build a real system

Velocity Components follows the useful part of this idea: developers should be able to inspect a component, understand its states, and decide whether it fits before adding it. Start with a maintained primitive, document its edge cases, then compose it into product patterns.

Browse Velocity Components for examples built as editable starting points rather than mystery boxes.

Sources and further reading

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.