If you’ve been building frontend interfaces over the last few years, you’ve probably felt the friction of component libraries. For a long time, my workflow involved installing a massive library, reading through endless documentation to find the specific prop that changes a button’s hover state, and eventually writing messy CSS overrides when the library refused to bend to the design requirements.
When I started heavily utilizing Tailwind CSS alongside React and Next.js, that friction became even more obvious. I wanted the speed of pre-built components without sacrificing control over the markup.
This is why my approach shifted entirely toward "copy-paste" component architecture, specifically using Shadcn UI.
Unlike traditional npm packages, Shadcn isn't installed as a dependency that lives hidden in your node_modules. Instead, you use a CLI to pull the actual component code—built on top of Radix UI primitives and styled with Tailwind—directly into your project folder.
This fundamentally changes how you build user interfaces:
- Total Ownership: Because the code lives in your
components/uifolder, you own it. If you need a specific animation on a dropdown menu or a custom variant for a badge, you just edit the file. There is no fighting with configuration objects. - Accessibility by Default: Building accessible modals, popovers, and select menus from scratch is notoriously difficult. Relying on headless UI primitives means keyboard navigation, focus management, and ARIA attributes are handled out of the box.
- Leaner Bundles: You only bring in the exact components you need. If a project doesn't require an accordion or a date picker, that code simply doesn't exist in your repository.
Recently, while building out data-heavy admin dashboards with complex tables and filtering requirements, having this level of granular control saved me hours of overriding default styles. It allows me to maintain a consistent design system that adapts perfectly to the project's unique theme, rather than looking like a generic clone of a popular framework. For any frontend developer looking to balance speed with customizability, moving away from rigid component libraries is a step worth taking.