The Hidden Cost of "Moving Fast": Why I'm Building My Own Components Again
Admin User
Author
I remember the exact moment I realized I'd been building in autopilot. I was three projects deep into Material-UI, trying to customize a button for the tenth time by layering sx props and styled() wrappers, and my colleague asked: "Do you actually know how this button works?"
I couldn't answer. Not really.
That question stuck with me. Here I was, a developer with years of experience, shipping production code every week, and I'd somehow outsourced one of the most fundamental parts of my job—understanding the components I build. I was fast, sure. But fast at what exactly? At reading library documentation? At debugging why my overrides weren't cascading correctly? That didn't feel like progress.
So I started an experiment. Instead of reaching for yet another component library, I'd build the basics myself. Just buttons, inputs, maybe a modal. Nothing revolutionary. Just enough to own the code I was shipping.
What Actually Changed When I Started Building
The first week was slower. I won't lie about that. A button took me three days because I kept second-guessing the prop interface. Should I support both size and scale? What about variant vs type? These aren't revolutionary questions, but they forced me to think instead of defaulting to someone else's API.
By week three, something shifted. I stopped thinking about libraries as solutions and started thinking about them as references. When I looked at how Chakra handles compound components, I wasn't admiring their code—I was learning why they made those tradeoffs. When I hit the fifth variant of my input component, I wasn't frustrated; I was designing an actual system instead of reacting to requirements.
The consistency thing is real too. My design tokens are now mine. When a designer says "make the padding tighter on buttons," I don't file an issue with a library maintainer. I change two lines of code and deploy.
The Performance Question Nobody Talks About
Here's what stuck with me: I added up the runtime cost of all those libraries. Tree-shaking helps, sure, but I was importing 40KB of code for a button component I'd modified into something almost unrecognizable.
My custom button component is 2KB, including all variants. Does that matter? In isolation, maybe not. Across a large application loaded on a 3G connection in Pakistan? Yeah, it matters.
More importantly, I know exactly what that 2KB does. No mystery bundle analysis runs. No surprise performance regressions after a minor version bump.
Where I'd Actually Push Back
Here's my honest take: I'm not advocating for every developer to stop using libraries. That would be absurd. But I think there's real value in understanding what you're using and why.
For a simple component system—buttons, inputs, cards, modals—building your own is probably worth it. You learn the fundamentals, you control the bundle, you own your design language.
For complex stuff like data tables, date pickers, or accessibility-heavy components? I'm not reinventing that wheel. Those require deep expertise I shouldn't replicate.
The key is intentionality. Before I install a library, I ask: Could I build this in a weekend? Will I need to heavily customize it? Is the tradeoff in performance worth the convenience?
Usually, the answer is "only for the big stuff."
A Practical Starting Point
Here's what a minimal, reusable button component actually looks like:
// Button.jsx
export const Button = ({
variant = 'primary',
size = 'md',
children,
...props
}) => {
const styles = {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
};
const sizes = {
sm: 'px-3 py-1 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg',
};
return (
<button
className={`rounded transition ${styles[variant]} ${sizes[size]}`}
{...props}
>
{children}
</button>
);
};
Not fancy. Not comprehensive. But mine. And scalable to whatever design system I need.
What's Your Threshold?
I'm genuinely curious where you draw this line. Do you build custom components on every project, or have you found a library that just works? And more importantly—does it feel like you're building or just configuring?
That distinction matters more than any library choice ever will.
Source: This post was inspired by "How I stopped relying on UI libraries and started building my own reusable components" by Dev.to. Read the original article