Skip to content

Installing from the registry

Components are not imported from a package. They are copied into your project by shadcn, and from that moment they are your files: edit them, delete them, rename their props. Nothing upstream reaches back in.

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/button.json

That is the whole distribution model, and the two things below make it practical: a way to install a working set in one command, and a way to install the same thing twice.

A product does not begin by wanting a Chip. It begins by wanting a screen, and reaches for a dozen primitives over the following week — twelve commands, each of them a small decision about whether this one is needed yet.

Three sets cover that opening week. They are read off what the line’s products actually converged on, not composed here.

Installs
app Button, Input, Textarea, Panel, Badge, Kbd, Dialog, ConfirmDialog, Drawer, Menu, Select, Combobox, Toast — what kilna has after moving over
forms Button, Input, Textarea, Select, Combobox, Chip
feedback Toast, Alert, Banner, ConfirmDialog
Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/app.json

A set carries no files of its own. It resolves into exactly the per-component installs you could have typed, so what lands on disk is identical either way, and nothing about the set survives in your project — there is no membership to leave. Having installed app, delete the Drawer you turned out not to need; nothing will disagree with you.

The theme is not part of any set. It is imported rather than copied for most products, and a set that reinstalled it would overwrite a file you may have already made yours:

@import 'tailwindcss';
@import 'dowel-ui/theme.css';
@import 'dowel-ui/accents/kilna.css';

A block is a screen made of the components: a list beside what is open in it, settings in sections, a sign-in, a dashboard’s first day. It installs like a component and brings the components it is made of:

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/settings-screen.json

It lands somewhere else, and on purpose. A component lands in components/ui and is kept as it came - a product’s check-registry holds that directory to the catalogue, and dowel diff says when a copy has drifted. A block lands in components/blocks and is the product’s from that moment: rename it to the screen it is, change what it shows. The two directories say which kind of file is which.

A block names the components it uses as @/components/ui/button, never as a relative path, and shadcn add rewrites that to wherever your components.json puts the ui alias - so a project whose components live elsewhere gets imports that resolve. The registry lists exactly those components as the block’s dependencies, read from its imports, so none can be left behind.

Blocks are named for what they are - list-detail-screen, login-screen - because they share one registry with the components, and list-detail would sit beside the ListDetail it is built on. They are held to what a component is held to: no word of their own (every word is in a words prop), only the scale, axe, a page on the stand and a picture in both themes. They are drawn together in kilna-lite, a small product made of nothing else.

/r/ always serves the newest build. That is the right default — a component copied today should be today’s component — but it means the URL in your notes does not describe what you installed, and a registry is not a package: nothing in your lockfile records which version of a Dialog was copied in.

So each minor is also served frozen, at a path that never changes again:

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/v0.12/dialog.json

Inside a pinned snapshot the cross-references point into the same snapshot. A component that reuses a sibling — Textarea shares the Input’s field styling — brings in that version of the sibling, so a set installed from v0.12 is the set that shipped with v0.12, and not a v0.12 Textarea beside whatever Input is current.

Reach for it when the install has to be repeatable: a scaffolding script, a migration you want to do in two steps, a second developer setting up the same screen next month. For everyday work, use /r/ and let the copy be current.

The catalogue lists every item served — the theme, the nineteen product accents, every component, and the sets:

  • /r/registry.json — served alongside the docs
  • dowel-ui/registry.json — the same catalogue inside the package, at the version you installed

The second is there for a reader with the package and without the network: a namespace registered in components.json, a script checking whether a component exists before shelling out to the CLI, an agent handed the dependency rather than the docs site.