Environment Variables
Registry-side and workspace-side environment variables.
Registry-side (required)
Set on the Vercel project or Docker host running the registry.
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string. This is the switch — its presence is what puts getDataProvider() into registry mode (see Model). Auto-injected by Vercel Postgres. |
AUTH_SECRET | NextAuth session-signing key. Generate with openssl rand -hex 32. |
HANDOFF_SYNC_SECRET | Bearer token for CLI push/pull and MCP (the legacy shared-secret credential, see API → Auth & scopes). Generate with openssl rand -hex 32. |
AUTH_URL | Public production URL, needed by NextAuth for OAuth callback redirects. Required on Vercel. |
HANDOFF_REGISTRY_MODE used to be listed here. It's inert on the current build path — only the
deprecated vercel-build command reads it, and DATABASE_URL alone is what puts the app in
registry mode.
Registry-side (optional)
| Variable | Purpose |
|---|---|
HANDOFF_APP_BASE_PATH | Sub-path the registry is served under (e.g. design-system for example.com/design-system). Empty by default. It sets Next's basePath and is the most widely-read env var in the app — internal links, asset URLs and API paths are all built from it, so a sub-path deploy that omits it produces broken links throughout. |
HANDOFF_DEFAULT_STACK_PROFILE | Default MCP stack-guide profile (e.g. bootstrap-handlebars, react-tailwind, tailwind-handlebars, react-scss) used for MCP project hydration before a workspace has pushed its own profile. |
HANDOFF_PROJECT_NAME | Display name shown before any project config has been pushed. |
HANDOFF_APP_URL | Public site URL used in password-reset / invite email links. |
RESEND_API_KEY | Resend API key for sending invite/reset emails. Unset → those emails are logged only, never sent (fine for local/dev). |
RESEND_FROM | Optional verified sender address; defaults to Resend's onboarding domain in dev. |
AUTH_GITHUB_ID / AUTH_GITHUB_SECRET | Enables GitHub as a login provider, see Auth. |
AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET | Enables Google as a login provider. |
AUTH_FIGMA_ID / AUTH_FIGMA_SECRET | Enables linking a Figma account (API access, not login), see Auth. |
HANDOFF_ADMIN_EMAIL / HANDOFF_ADMIN_PASSWORD | Non-interactive alternative to the /setup UI, see First-admin setup. |
HANDOFF_AI_API_KEY | OpenAI key for AI features (pattern generation, design-to-component, vision). Omit if proxying AI through a remote HANDOFF_CLOUD_URL. |
HANDOFF_AI_MODEL | Model for pattern generation/vision tasks. Defaults to gpt-4.1. |
HANDOFF_AI_REQUEST_TIMEOUT_MS | Chat-completion timeout in ms. Default 180000. |
HANDOFF_COMPONENT_GEN_MODEL / HANDOFF_VISION_MODEL / HANDOFF_REFERENCE_MODEL | Model overrides for design-to-component generation, vision comparison, and reference-material generation, respectively. |
CRON_SECRET | Bearer the Vercel Cron job presents to POST /api/handoff/ai/design-jobs/run, the drain for queued AI design images. Unset means the route hard-fails with a 503 and queued images never generate, which is exactly how a demo deployment silently stalled. Generate with openssl rand -hex 32. |
HANDOFF_CLI_JWT_SECRET | Signing key for CLI sync JWTs (handoff-app login tokens). Optional, falls back to a value derived from AUTH_SECRET; set it only to rotate CLI tokens independently of sessions. |
AI vars are about the design-to-component workbench, not MCP
The HANDOFF_AI_* / HANDOFF_COMPONENT_* / HANDOFF_VISION_* variables configure the
registry's own AI-assisted design workbench (design artifacts → generated components), a
separate feature from MCP, which doesn't call an LLM itself. See
Concepts → Design artifacts.
Asset storage (optional)
Uploaded assets are stored in Postgres by default. Configure either backend below to offload them:
| Variable | Purpose |
|---|---|
HANDOFF_S3_BUCKET / HANDOFF_S3_REGION / HANDOFF_S3_ACCESS_KEY_ID / HANDOFF_S3_SECRET_ACCESS_KEY | All four required together to enable the S3 asset backend; if any is missing, S3 is treated as unconfigured. |
HANDOFF_S3_CDN_URL | CDN origin to serve S3 objects from. Falls back to the bucket's own https://<bucket>.s3.<region>.amazonaws.com URL. |
HANDOFF_CLOUDFRONT_DISTRIBUTION_ID | CloudFront distribution to invalidate when an asset changes. |
BLOB_READ_WRITE_TOKEN | Vercel Blob token for design-artifact images. Unset (local dev / workspace mode) degrades gracefully — images stay inline instead of being offloaded. |
Workspace-side (in the design-system repo)
| Variable | Required | Purpose |
|---|---|---|
HANDOFF_CLOUD_URL | For push/pull | URL of the registry this workspace pushes to and pulls from. |
HANDOFF_CLOUD_TOKEN | If not using handoff-app login | Bearer token — must equal the registry's HANDOFF_SYNC_SECRET. |
DATABASE_URL | Never | Workspaces are filesystem-only. Setting this would switch the local app into registry mode, which is almost never what you want on a workspace machine. |
After handoff-app login, the resulting JWT in .handoff/cli-auth.json takes precedence over
HANDOFF_CLOUD_TOKEN, you can omit the token env var once logged in.
A handful of other workspace-side variables control config resolution and path layout
(HANDOFF_WORKING_PATH, HANDOFF_FIGMA_PROJECT_ID, HANDOFF_DEV_ACCESS_TOKEN, …), see
Workspace → handoff.config.* resolution
for the full list.