Something new is coming.Join the waitlist
All posts
tent ui team

Why We Built tent ui: Design Systems Without the Overhead

The story behind tent ui — a small, opinionated component library that prefers copy-paste source over npm packages, and ships only the components we actually use in production.

design systemsshadcn uireactphilosophycomponent library

There are already hundreds of React component libraries. Adding another one needs a reason. This post is that reason — what tent ui is for, what it deliberately does not do, and how it compares to the alternatives we used before building it.

This is not a marketing piece. It is the design rationale, written for engineers who are deciding whether to adopt a UI library, build their own, or extend one of the existing options.


The problem we kept hitting

Every product team eventually owns a small pile of components: animated buttons, file folders, password inputs, world maps, inline editors. Each one is too specific to belong in a generic library, but too valuable to rewrite for every project.

For a few years we copied these between repos by hand. Sometimes they were the same component, just three months stale. Sometimes the styling drifted because two engineers each "improved" it independently. The cost was not the original implementation — it was the long tail of small inconsistencies that accumulated across projects.

We tried three solutions before landing on tent ui:

  1. An internal npm package — versioning was painful, breaking changes spread invisibly, and bumping a major required coordinating across four repos
  2. A monorepo with shared components — solved the version drift but tied every project to the same release cadence, which broke down when one product needed a faster iteration loop
  3. Pure copy-paste with no shared source of truth — fastest to ship, slowest to maintain, and over six months the same bug fix landed differently in every codebase

shadcn/ui showed a fourth option. Treat components as code you own, not packages you depend on. Distribute them through a CLI registry that copies the source into your repo. The component becomes part of your codebase the moment you add it, and you upgrade by re-running the CLI, not by bumping a version pin.

tent ui is what happens when you take that pattern and add a small set of opinionated components on top.


What tent ui is

A custom shadcn registry. You install components by URL:

npx shadcn@latest add https://ui.srb.codes/r/animated-save-button.json

The CLI fetches the source from our registry, writes it to your project, installs any missing dependencies, and gets out of the way. There is no @srbcodes/ui npm package. There is no theme provider. There is no peer-dependency matrix. The components live in your repo, in plain TypeScript, formatted with whatever tools you already use.

Right now tent ui ships:

  • A focused set of base UI primitives — buttons, dialogs, inputs, sidebars — that match shadcn/ui defaults so the two libraries coexist cleanly
  • A handful of specialized components built on top — animated save button, animated arrow, password input with strength meter, inline edit, world map, file folder
  • Tailwind v4 tokens that map onto your existing design system rather than fighting it

What it does not ship:

  • A 200-component grab bag covering every imaginable use case
  • Pre-built marketing pages or template repos
  • A hosted theme configurator
  • Any runtime configuration whatsoever

That is intentional. Every component in the registry has a real production user — usually us. We do not ship speculative components that "might be useful." If we have not used it, it is not in the library.


How this compares to alternatives

We have built production projects on most of the popular React UI libraries. Here is a fair, opinionated take on where each one fits:

  • shadcn/ui — the foundation. If you are building a generic admin or SaaS UI, you may not need anything more than shadcn/ui itself. tent ui is purely additive.
  • Magic UI — beautiful animated marketing components. Picks up where tent ui stops if you are building a landing page that needs flashy transitions.
  • Aceternity UI — dense set of animated components, light shadcn-CLI integration. Good for landing pages, less aligned with app UI.
  • Origin UI, Tremor, MUI, Chakra, Mantine — all excellent for their target audience. None of them follow the copy-paste registry pattern, which means you trade ownership for a larger catalog. That is a fine trade for many teams.

If you compared tent ui side-by-side with these alternatives, you would notice it has fewer components. That is the point. We would rather ship 14 well-tuned components than 80 components we do not maintain.


What "without the overhead" means

The phrase in the title is doing real work. Here is what we mean.

No version drift. When you add a component, you get a snapshot of the source at that moment. We can ship a new version of the same component tomorrow, and your old code does not break — because nothing in your build talks to our registry at runtime. Upgrades are explicit, file-level diffs you review like any other PR.

No theme provider. Components reference CSS variables (--primary, --muted, --ring) defined in your globals.css. If your app already uses shadcn/ui, tent ui automatically inherits the theme. If you want to recolor a single component, edit its file. There is no theme={...} prop, no context, no provider tree.

No bundle surprises. Because each component is its own file in your repo, your bundler tree-shakes naturally. Tailwind purges unused classes. There is no library-side runtime to ship.

No abstraction tax. The components are plain React and Tailwind. They do not invent new APIs. If you have used useState and <button>, you can read every line of every component in the library. That matters for review velocity and onboarding.


Where this approach has limits

Honest tradeoffs:

  • You own the upgrades. When we ship a fix, you re-run the CLI to pull the latest source. There is no automatic patch. For most teams this is a feature, but if you want zero-effort upgrades, tent ui is not the right call.
  • You own the bugs you introduce. If you edit a component and break it, that is your bug, not ours. The registry pattern trades flexibility for a slightly steeper accountability curve.
  • The catalog is small. If you need a date range picker, a Gantt chart, and a virtualized data grid by Friday, tent ui will not get you there. shadcn/ui plus a specialized library will.
  • Documentation drift is real. Because every consumer's copy of the source can diverge, our docs describe the canonical version. We try to keep examples close to defaults, but heavily customized installations will need to maintain their own docs internally.

Who this is for

tent ui is a good fit if you:

  • Already use shadcn/ui and want a few extra polished primitives that fit the same conventions
  • Care about animation quality and want it pre-built rather than written from scratch
  • Prefer to own your component source rather than rent it from npm
  • Ship in TypeScript and value strict types and clean APIs

It is probably not for you if you want a comprehensive UI kit, hosted infrastructure, or a library that updates itself. Those are valid needs — they just are not what we are solving.


What is next

The component catalog is small on purpose, but it is growing. Recent additions include the world map, animated save button, and inline edit. Components on the near-term list are sparkline charts, a password reveal that pairs with the strength meter, and a handful of layout primitives for marketing pages.

If there is a component you keep copying between projects and wish lived in a registry, open an issue. We are small enough that real engineers read the requests, and the bar for inclusion is "we would use this on a real project."

That is the whole pitch. A small library, in your repo, ready to edit. Design systems without the overhead.