Component Library
Component libraries are powerful once they're up and running. The trick is to actually get them up and running fast.
At my time at U.P., we kept building greenfield projects from scratch. As you can imagine, it was a massive waste of time—time that could have been spent collecting data and prototyping better experiences. We decided to unify all of our frontends using a team-picked frontend technology.
To make this transition smoother, we built a component library using shadcn-svelte for pre-styled, composable UI components, Lucide icons for a consistent iconography system, and SvelteKit as the framework. We also set up a private npm registry within our GitHub company space to manage and distribute the package across projects seamlessly.
This post will walk through the process of setting up a scalable, maintainable component library—from tooling decisions to implementation and publishing—so your team can stop reinventing the wheel and start building real value faster.

We chose shadcn-svelte as our foundation because it provided a solid starting point with all the complex components we needed. From forms to page-level components, everything could be combined seamlessly while maintaining consistent behaviour.
The real beauty of this package is how DRY it is—UI elements like input fields, calendars, and more all share the same underlying button, label, and text subcomponents. No more chasing down a dozen variations of the same thing—everything just worked. It was a game-changer. (And no, I’m not getting a kickback—just try it yourself.)
This approach gave us a unified, consistent UI across all our frontend projects, reducing fragmentation and making development significantly more efficient.

Integrating third-party packages into our component library was seamless. One example was a phone validation package, which we incorporated effortlessly thanks to Svelte’s simplicity and shadcn-svelte’s structured approach.
For this, we added a listener to our select field to update the validation rules based on the chosen country. Since this was a high-priority delivery, we leveraged packages built-in input field alongside our validation package, significantly speeding up development. And because shadcn-svelte is built with TailwindCSS, maintaining a consistent appearance was effortless—no fiddling with mismatched styles or overrides.

The final example above is the date range picker, which brings together a calendar, a range selection field, and an input field into a single cohesive component. We customised this to fit our specific needs, and thanks to shadcn-svelte’s compositional patterns, making adjustments was incredibly efficient.
By updating the underlying subcomponents, we automatically ensured consistency across the larger, more complex components—saving time and keeping everything aligned without extra effort.

By leveraging these base and subcomponents, we could rapidly assemble complete UI experiences, as demonstrated above. We built a wrapper component to handle the outer structure, then placed our field wrappers inside it.
This approach standardised field interactions, allowing us to listen to inputs directly, apply any necessary validation, and seamlessly pass the results back to our components. It streamlined our workflow and ensured consistency across the entire UI.
Get in touch
I am always free to discuss new projects, opportunities or any assistance you may require.
Responses usually take less than 24 hours.