7.2 KiB
hanzoai/shadcn — LLM context
What this is. Everything shadcn-lineage at Hanzo: the shadcn CLI, the
component registry it serves, the two docs sites that publish that registry, and
the templates/* projects it scaffolds. Split out of hanzoai/ui so each repo
is one thing — hanzoai/ui is now @hanzo/ui@8 on @hanzo/gui and nothing
shadcn.
The repo's root commit is shadcn's (2023-01-24 · shadcn · feat: initial commit). The history came across per-path with git filter-repo, because for
this side the provenance IS the attribution. Keep it.
Layout
shadcn/
pkg/
cli/ the `shadcn` CLI (package name `shadcn`, private, bin dist/index.js)
components/ @hanzo/shadcn — the same components as a published package
tests/ integration tests; drives the built CLI against fixtures
app/ ui.hanzo.ai — docs site (@hanzo/ui-web) + app/registry/** SOURCE
apps/v4/ upstream shadcn v4 docs + registry (port 4000)
templates/ what `shadcn create` scaffolds (next, vite, astro, react-router, start)
tests/ Playwright e2e of app/ (port 3333)
skills/shadcn/ agent skill for the CLI
pkg/* is the one package root. templates/* are NOT workspace members — they
are scaffolds with their own manifests, and globbing them into the workspace
would install eleven starter apps on every pnpm install.
Two doors to the same components, on purpose
| how you get it | who owns the file | |
|---|---|---|
npx shadcn add button |
CLI copies source into your project | you do — edit freely |
pnpm add @hanzo/shadcn |
normal dependency | we do — you upgrade it |
Same Radix primitives, same standard shadcn tokens (bg-primary,
text-muted-foreground, …). @hanzo/shadcn ships no CSS of its own; it renders
against whatever host defines those variables.
The registry
app/registry/** is the source of truth; app/__registry__ and app/public/r
are generated. The chain is pnpm registry:build → registry:api →
next build, all inside app/, and the static export is the site.
- Index is
Index[style][name], notIndex[name]. Reading it flat renders nothing and raises no error. - Tailwind here is the deliverable. These files are what the CLI hands customers. Do not "clean up" a registry.
- Tailwind reads SOURCE TEXT.
grid-cols-${n}never becomes a rule, and the failure hides when a neighbouring file spells one literally and lends you its rule. A count becomes an inline style; a value off a fixed scale becomes a literal lookup table.
https://ui.hanzo.ai/r/{name}.json currently 404s — the site is live and
serving, but the /r/ payload is not in the deployed export. components.json
and the CLI contract both name that path, so the registry is unreachable to any
consumer configured for @hanzo. Pre-existing; not caused by the split.
The CLI
pkg/cli, package name shadcn, private: true — we do not publish it; it is
upstream's name. It is verbatim upstream: grep -ri hanzo pkg/cli/src returns
nothing.
- Default registry is
https://ui.shadcn.com/r, overridden byREGISTRY_URL(src/registry/constants.ts). Pointing it at ours is a config change, not a code change. - Templates come from
git clone --sparseofSHADCN_GITHUB_URL(defaultshadcn-ui/ui) unlessSHADCN_TEMPLATE_DIRis set — which is whatpnpm --filter shadcn start:devdoes. So in production the CLI scaffolds from upstream, not fromtemplates/here. src/templates/laravel.tsnameslaravel-app, which has no directory here;templates/monorepo-nextis referenced by nothing. Upstream drift, both.
npx @hanzo/ui add button does not work and never did. @hanzo/ui has no
bin — npm answers "could not determine executable to run". The CLI-bearing
published package is @hanzo/[email protected] (bin: hanzo-ui). Do not repeat
the npx @hanzo/ui add line in docs.
How this ships
push -> git.hanzo.ai/hanzoai/shadcn CANONICAL
.hanzo/workflows/cicd.yml the whole pipeline, from hanzo.yml
.hanzo/workflows/registries.yml the v4 registry check
-> ghcr.io/hanzoai/shadcn the ui.hanzo.ai image
-> hanzoai/universe charts/app/values/hanzo/ui.yaml
names the tag that is live
github.com/hanzoai/shadcn a mirror; it runs nothing
.hanzo/workflows, never .github/workflows — the forge resolves only the
former, and github.com has no runner for the hanzo-build-* labels, so a caller
in the wrong directory is a gate that can never be scheduled.
app/ is a Next static export; Dockerfile copies app/out into
ghcr.io/hanzoai/static. The ingest key is baked at build from KMS
deploy/PUBLISHABLE_KEY via hanzo.yml's build_secrets — the only lane that
can supply it — and the Dockerfile fails closed on an empty or pk_-prefixed
key, because a keyless static export looks correct and reports nothing.
The image lane needs one credential this repo does not have yet
cicd fails at "Fetch deploy credentials from KMS", and nothing after it
runs. The images: block declares build_secrets: [PUBLISHABLE_KEY], so
hanzoai/ci reads KMS deploy/PUBLISHABLE_KEY using the runner's machine
identity — and that identity is provisioned on hanzoai/ui, where the same step
passes, but not here. Measured on both: same reusable, same step, ui green,
shadcn red.
The fix is repo configuration, not code: give hanzoai/shadcn the
KMS_CLIENT_ID and KMS_CLIENT_SECRET secrets hanzoai/ui already has. The
block stays declared because it is where the site is built from now; deleting it
would leave ui.hanzo.ai with no builder in any repo and nothing failing to say
so. The two test: gates both pass — components (typecheck, build, and the
tarball/exports assertion) and cli (build, then run the binary).
Until the credential lands, ui.hanzo.ai keeps serving the digest pinned in
hanzoai/universe charts/app/values/hanzo/ui.yaml, which still names
ghcr.io/hanzoai/ui:5.7.7. Repin it to ghcr.io/hanzoai/shadcn:<tag> on the
first green image build — not before, or the pod pulls a tag that does not exist.
Gotchas
pkg/testsdoes not run.pnpm --filter tests testdies in globalSetup withReferenceError: __vite_ssr_exportName__ is not defined— the package pinsvitest ^2.1.9and its vite-node cannot read the SSR transform the workspace'svite 8emits. Measured identical onhanzoai/uiat07d21522b, before this repo existed. Fixing it is a version decision (align the pin, or give the package its own vite), so thecligate builds and runs the binary and leaves the suite out rather than shipping a gate that cannot pass.scripts/sync-templates.shpushes togithub.com/shadcn/<name>— an org we do not control. It is upstream's, manual-only, and running it attempts writes to someone else's repos.tests/scripts/*.mjsandtests/component-health-check.tsimportpkgs/ui/…, a path that has not existed for some time. Dead before the split.tests/comprehensive.spec.tsandtests/theme-dropdown.spec.tshardcode port 3003;playwright.config.tsserves 3333.