Skip to content
Component installs need the registry setup— the Base UI shadcn project, the @vegastack namespace and the Cloudflare Access service token.
VegaStack Design

Install From VegaStack Registry

Configure shadcn to consume the private VegaStack Base UI registry.

Last updated

New project? Follow the Quickstart — the full zero-to-dashboard walkthrough. Building for a client? See Client projects. This page is the registry-setup reference the component pages link to; the Guides section covers auth, updates, theming, production readiness, and troubleshooting in depth.

VegaStack components are copy-in registry items. One public npm package provides the runtime layer (utilities, icons, Tailwind preset, CLI); component source comes from the private shadcn registry. Design tokens ship separately as the zero-dependency @vegastack/design-tokens (installed automatically as a dependency of @vegastack/design).

Public Packages

Install the public layer first. It does not require VegaStack credentials.

npm install @vegastack/design

Import the VegaStack preset in your app stylesheet. preset.css bundles Tailwind, the theme tokens, the base a11y layer, and the utility helpers in one import.

@import "@vegastack/design/preset.css";

Don't skip the base layer. The preset bundles the tokens' base.css, which ships the global :focus-visible ring, the prefers-reduced-motion reset, pointer cursors, and portal isolation. By design, components carry no focus ring of their own — keyboard focus visibility (WCAG 2.4.7) comes from this layer. If you import @vegastack/design/theme.css directly instead, you must also @import "@vegastack/design/base.css";, or focus rings disappear for shipped users.

Tokens without React? A non-Tailwind or non-React consumer (native app, token pipeline, marketing site) can install just the design contract: npm install @vegastack/design-tokens — zero dependencies, pure CSS/JSON.

shadcn Base UI

Initialize shadcn with the Base UI implementation.

npx shadcn@latest init --base base

Verify the resolved project base before installing components.

npx shadcn@latest info --json

The result must report "base": "base". A Radix-resolved config is not a valid VegaStack component consumer.

Registry Namespace

Internal consumers add the VegaStack namespace to components.json. Production registry reads require Cloudflare Access service-token headers; browsing the public docs does not authenticate /r/* registry access.

{
  "registries": {
    "@vegastack": {
      "url": "https://design.vegastack.com/r/{name}.json",
      "headers": {
        "CF-Access-Client-Id": "${CF_ACCESS_CLIENT_ID}",
        "CF-Access-Client-Secret": "${CF_ACCESS_CLIENT_SECRET}"
      }
    }
  }
}

The docs app dogfoods the same registry shape against a local server:

{
  "registries": {
    "@vegastack": {
      "url": "http://localhost:4000/{name}.json"
    }
  }
}

Integrity Preflight

Verify each registry item before copy-in, save the verified bytes, then verify the files written by shadcn add. This is the fail-closed flow that closes the registry fetch time-of-check/time-of-use gap.

VEGASTACK_VERIFY_DIR="$(mktemp -d "${TMPDIR:-/tmp}/vegastack-verify.XXXXXX")"
VEGASTACK_ITEM="$VEGASTACK_VERIFY_DIR/button.json"
npx --package=@vegastack/design vegastack-design verify \
  --save "$VEGASTACK_ITEM" button
# Retain this before running shadcn so it remains independent of the saved file during copy-in.
VEGASTACK_EXPECTED_INTEGRITY="$(node -e \
  'process.stdout.write(JSON.parse(require("node:fs").readFileSync(process.argv[1], "utf8")).meta.integrity)' \
  "$VEGASTACK_ITEM")"

The save path must be new; the verifier refuses to overwrite an existing file or follow a symlink.

Use --hash-only only for local development when the signed manifest or cosign is unavailable. The full mode verifies the signed manifest identity and the item hash.

Add Components

After the namespace is configured and the preflight passes, install components by name.

pnpm dlx shadcn@latest add @vegastack/button
pnpm dlx shadcn@latest add @vegastack/field

Then prove the copied files match the saved item bytes.

npx --package=@vegastack/design vegastack-design verify \
  --post-write --item "$VEGASTACK_ITEM" \
  --expected-integrity "$VEGASTACK_EXPECTED_INTEGRITY" --target-dir .

The registry item installs its npm dependencies, registry dependencies, and source files. (The current shadcn CLI strips the stamped provenance header during copy-in — that's expected; update tracking identifies copies by filename and compares content, no header needed.)

Updating components

Registry components are copy-in — you own the copy, so updates are pulled, never pushed. Tracking is by content: copies are identified by filename against the registry index and compared alias-normalized (a provenance header, when present, is only a fast-path pin). One command shows what's stale against the live registry:

npx --package=@vegastack/design vegastack-design check-updates
  ⬆  button   0.1.0 → 0.2.0   update available
  ≈  card     → 0.2.0         differs from registry (update or local edits — review with --diff)
  ✓  field    0.2.0           up to date
  ?  legacy   0.1.0           not in registry (renamed/removed)

Status is by content, so a component reads up to date even when the registry's global version bumped but that component's content didn't change; means the bytes diverged — an upstream update or your local edits. Review and apply per component:

npx shadcn@latest add @vegastack/button --diff       # see exactly what changed
npx shadcn@latest add @vegastack/button --overwrite  # take it (re-apply any local edits)

--overwrite replaces the file, so git diff first if you customized it. For CI drift detection, vegastack-design check-updates --fail-on-update exits non-zero when anything is stale. The CLI reads the @vegastack registry URL + headers from components.json${ENV} placeholders expand from .env.local / .env or the shell (same as shadcn), falling back to VEGASTACK_REGISTRY + CF_ACCESS_*. Before attaching any credential it requires the exact trusted HTTPS origin (https://design.vegastack.com by default) and rejects redirects. A custom credentialed registry must set VEGASTACK_TRUSTED_REGISTRY_ORIGIN in operator-controlled process/CI configuration; checkout-local dotenv cannot change that trust anchor.

External/client projects do not receive registry service tokens. VegaStack copies component source during development, and the shipped app remains self-contained.

On this page