Getting started

Installation

Point the shadcn CLI at the @woohl registry.

1. Add the registry

The registry is a set of static JSON files. Add it to your components.json:

components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "aliases": {
    "components": "@/components",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "utils": "@/lib/utils"
  },
  "registries": {
    "@woohl": "http://localhost:3009/r/{name}.json"
  }
}

Namespaced dependencies

Internal dependencies are written @woohl/cva, not cva. A bare name is resolved by the CLI against shadcn's registry rather than this one, and the install fails with a confusing "item not found" from a URL you never configured.

2. Install the token layer first

Every visual item assumes the tokens are present. The CLI will pull them in for you, but installing them first makes the first run easier to read:

bunx --bun shadcn@latest add @woohl/tokens

Then wire the stylesheet, after Tailwind and before anything else:

app/globals.css
@import "tailwindcss";
@import "../design-system/index.css";
@source "../design-system";

@source matters when the folder sits outside the directory Tailwind scans by default. Without it, classes used only inside a component are dropped in production and the component silently loses its styling.

3. Pick a theme

Set the product theme on the document once:

app/layout.tsx
<html lang="en" data-theme="seller">

Four exist: buyer, seller, admin and bulk. They change the semantic layer only — no component knows which one is active.

4. Install components

bunx --bun shadcn@latest add @woohl/button
bunx --bun shadcn@latest add @woohl/dialog
bunx --bun shadcn@latest add @woohl/product-card

Each pulls its own npm packages and registry prerequisites.

Running against a local registry

While developing the system itself, serve it and point @woohl at it — the whole entry, not a second one:

cd design-system && bun run build && bun run start -p 3003
components.json (temporarily)
"registries": { "@woohl": "http://localhost:3003/r/{name}.json" }

A second registry name will not work

Adding @woohl-local alongside @woohl looks tidier and fails: the CLI does not resolve the alternate namespace. Installing by direct URL (bunx --bun shadcn add http://localhost:3003/r/button.json) fails for a subtler reason — the item is fetched from localhost, but its registryDependencies are namespaced @woohl/... and still resolve through whatever @woohl points at, so the install dies on the production URL. Point @woohl itself at localhost.

Environment variables in the registry URL

Do not write the URL as ${REGISTRY_URL}/r/{name}.json. The variable does expand, but the CLI then resolves your baseColor against the registry origin and the install fails on a missing /colors/neutral.json. Use two named registries instead.

On this page