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

Registry access & auth

Configure authenticated registry access locally and in CI with Cloudflare service-token headers and secret-safe placeholders.

Last updated

Components are distributed from https://design.vegastack.com/r/*, a private shadcn registry protected by Cloudflare Access. Registry JSON is always machine-authenticated — that never changes, whoever you are and however you reach the site.

SurfaceAccess
Every non-registry site routeAnonymous. Operations pages are intentionally unlisted and noindex, not access-controlled
/r/*Cloudflare Access service token (never an identity login)

The registry's service-token requirement is independent of the rest of the site's public visibility: making every documentation and operations route anonymous does not open /r/*. A browser session is never registry authorization.

Registry administrators provide a Client ID and Client Secret. Treat both values as credentials: keep them out of source control, browser bundles, logs, screenshots, and NEXT_PUBLIC_* variables.

Every tool that talks to the registry sends the same two headers:

CF-Access-Client-Id: <client-id>.access
CF-Access-Client-Secret: <client-secret>

Two common configuration mistakes:

  • The .access suffix is part of the Client ID—keep it.
  • Store only the values. A value such as CF-Access-Client-Id: abc… produces a doubled header and fails authentication.

Configure a project

components.json references environment variables; the CLI and vegastack-design expand ${…} from the shell, .env.local, or .env:

components.json (registries block)
"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}"
    }
  }
}
.env.local (gitignored)
CF_ACCESS_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.access
CF_ACCESS_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Commit an .env.example containing empty placeholders, never working values.

Configure CI

Store both values as masked CI secrets and expose them only to steps that need registry access:

.github/workflows/ci.yml (fragment)
- run: pnpm check-updates --fail-on-update
  env:
    VEGASTACK_TRUSTED_REGISTRY_ORIGIN: https://design.vegastack.com
    CF_ACCESS_CLIENT_ID: ${{ secrets.CF_ACCESS_CLIENT_ID }}
    CF_ACCESS_CLIENT_SECRET: ${{ secrets.CF_ACCESS_CLIENT_SECRET }}

check-updates validates this exact HTTPS origin before attaching credentials and rejects redirects. Keep the trust anchor in operator-controlled CI configuration, not in a checkout-local dotenv file.

Verify access

curl -sS -o /dev/null -w "%{http_code}\n" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
  https://design.vegastack.com/r/registry.json
ResultMeaning
200The token is accepted and registry operations can proceed.
401 or 403Values are missing, invalid, expired, or were stored with their header names.
Any other statusStop and report the response; do not modify the URL or bypass Access.

External projects

External teams do not receive registry credentials. Public npm packages remain available, while component source is copied into the external codebase by an authorized VegaStack engineer. The shipped application has no runtime dependency on the registry.

For agents: if a registry request returns 401 or 403, stop and surface the authentication failure. Never retry with modified URLs or attempt to bypass Access.

On this page