Nextbase Docs
Nextbase Docs
HomeBlogWelcome to Nextbase v5!Choose your starterGetting startedLocal Supabase per agent
TanStack + Cloudflare D1InstallationEnvironment variablesAuthenticationAgent connectionsProject structureDeployment
AuthenticationWorkspaces and the admin area
Building with agentsEmails with Resend
TroubleshootingNextbase v5
The 8 starter kitsTanStack + Cloudflare D1

Environment variables

Every secret and Wrangler variable the web Worker, the admin Worker and the jobs Worker read, where it lives and where to get the value.

This kit has no browser-exposed environment variables. Everything below is read inside a Cloudflare Worker and never shipped to the client. Configuration is split in two places:

  • Secrets go in .dev.vars files locally and in Worker secrets (wrangler secret put) when deployed. The templates are apps/web/.env.example, apps/admin/.env.example and apps/jobs/.env.example.
  • Non-secret variables live in the vars blocks of apps/web/wrangler.jsonc, apps/admin/wrangler.jsonc and apps/jobs/wrangler.jsonc, once per environment (top level for local, then env.preview and env.production).

Copy the templates only when the .dev.vars files are missing. See installation for the commands.

Keep secrets out of vars

The repository's runbook says Unkey, OpenAI, Stripe, Resend and Cloudflare credentials must never appear in vars, client loader data, logs or Queue payloads. Use Worker secrets for anything in the secrets tables below.

Web Worker secrets

File: apps/web/.dev.vars (template apps/web/.env.example). Deployed: pnpm --filter @nextbase/web exec wrangler secret put <NAME> --env <preview|production>.

VariableRequiredWhat it is forWhere to get the value
BETTER_AUTH_SECRETRequired outside localhostSigns Better Auth sessions and tokens. The Worker refuses to start on a non-local SITE_URL without it. Locally a development fallback is used.Generate at least 32 random characters.
ANALYTICS_PSEUDONYM_SECRETOptional, recommendedHMAC key that pseudonymizes user IDs in product_analytics_events. Falls back to the Better Auth secret. Rotating it breaks the link to earlier pseudonyms on purpose.Generate an independent random secret.
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETOptionalEnables the Google sign-in button. Both must be set.Google Cloud OAuth client.
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETOptionalEnables the GitHub sign-in button. Both must be set.GitHub OAuth app.
TWITTER_CLIENT_ID / TWITTER_CLIENT_SECRETOptionalEnables the Twitter sign-in button. Both must be set.Twitter developer app.
STRIPE_SECRET_KEYOptionalStripe API access for Checkout, the billing portal and catalog reads.Stripe dashboard, API keys.
STRIPE_WEBHOOK_SECRETOptionalVerifies the raw body of POST /api/stripe/webhooks.Stripe webhook endpoint signing secret.
OPENAI_API_KEYOptionalAI SDK streaming chat at /api/chat.OpenAI API keys.
UNKEY_ROOT_KEYOptionalCreates and verifies developer API keys for /api/v1/me and /user/api-keys.Unkey dashboard, root key.
UNKEY_API_IDOptionalThe Unkey API the keys belong to. Treated as public and also present in Wrangler vars.Unkey dashboard, API ID.
API_CORS_ORIGINSOptionalComma-separated exact origins allowed to call the public API. Default http://localhost:5173. Also set in Wrangler vars.Your deployed origin, for example https://app.example.com.

RESEND_API_KEY, CLOUDFLARE_API_TOKEN and CLOUDFLARE_ZONE_ID are not in the web template and not in the web Env type. Email delivery and cache purges happen in the jobs Worker, so those secrets belong only there.

Admin Worker secrets and local values

File: apps/admin/.dev.vars (template apps/admin/.env.example). Deployed: pnpm --filter @nextbase/admin exec wrangler secret put <NAME> --env <preview|production>.

VariableRequiredWhat it is forWhere to get the value
SITE_URLIn the templateThe admin app's own origin, http://localhost:5174 locally. Also set in the admin Wrangler vars.Your admin origin.
WEB_APP_URLIn the templateThe customer web app's origin, http://localhost:5173 locally. Used to build the impersonation handoff and the links in magic links issued from the admin console. Also set in the admin Wrangler vars.Your web origin.
ADMIN_APPIn the template, trueTurns the shared code into the administrator app: the Admin MCP audience, the nextbase-admin cookie prefix. Also set in the admin Wrangler vars.Keep true.
BETTER_AUTH_SECRETRequired outside localhostAn independent secret for the admin app's own Better Auth instance. Never reuse the web Worker's value.Generate at least 32 random characters.

The admin Worker shares the web app's code, so the optional web secrets (social provider keys, Stripe, OpenAI, Unkey) are read there too when you set them. Its login page shows a social button only for a provider configured on the admin Worker.

Jobs Worker secrets

File: apps/jobs/.dev.vars (template apps/jobs/.env.example). Deployed: pnpm --filter @nextbase/jobs exec wrangler secret put <NAME> --env <preview|production>.

VariableRequiredWhat it is forWhere to get the value
RESEND_API_KEYRequired in productionSends queued email.send jobs through Resend. When empty, emails are written to the dev_email_inbox D1 table instead.Resend dashboard.
STRIPE_SECRET_KEYOptionalLets webhook processing re-fetch current Stripe objects before updating D1.Stripe dashboard, API keys.
UNKEY_ROOT_KEYOptionalRevokes provider API keys through the outbox after a local revocation.Unkey dashboard, root key.
CLOUDFLARE_API_TOKENRequired in deployed environmentsZone-scoped token used by cache.purge jobs. Missing credentials are tolerated only for localhost.Cloudflare API token with cache purge for one zone.
CLOUDFLARE_ZONE_IDRequired in deployed environmentsThe zone whose cache is purged.Cloudflare dashboard, zone overview.

Web Worker vars

Set in apps/web/wrangler.jsonc for each environment.

VariableLocal defaultWhat it is for
APP_NAMENextbaseShown in the UI and used as the Better Auth app name and in email subjects.
SITE_URLhttp://localhost:5173The canonical origin. Better Auth baseURL and trusted origin, cross-origin mutation check, telemetry origin check, and the origin of the User MCP endpoint.
ADMIN_APP_URLhttp://localhost:5174The admin app's origin. /stop-impersonating sends the administrator back to ADMIN_APP_URL + /app-admin/users.
ADMIN_EMAILadmin@nextbase.localSupport address shown in emails.
UNKEY_API_IDemptyPublic Unkey API identifier for developer keys.
API_CORS_ORIGINShttp://localhost:5173Exact-origin CORS allowlist for /api/v1/me. Keep preview and production lists separate and never use *.

Admin Worker vars

Set in apps/admin/wrangler.jsonc for each environment.

VariableLocal defaultWhat it is for
APP_NAMENextbaseSame role as on the web Worker.
SITE_URLhttp://localhost:5174The admin origin. Better Auth baseURL, same-origin check for mutations, and the origin of the Admin MCP endpoint and its OAuth issuer.
ADMIN_APPtrueMarks this Worker as the administrator app. The MCP handler serves only the admin audience when it is true.
WEB_APP_URLhttp://localhost:5173The web origin. Impersonation redirects to WEB_APP_URL + /auth/impersonate; cache purges and magic links issued from the console use it as the public site origin. Impersonation fails if it is missing.
ADMIN_EMAILadmin@nextbase.localSupport address.
UNKEY_API_IDemptyPresent for the shared code; developer API keys are managed on the web app.
API_CORS_ORIGINShttp://localhost:5173Present for the shared code; the public API route /api/v1/me exists only on the web app.

Jobs Worker vars

Set in apps/jobs/wrangler.jsonc for each environment.

VariableLocal defaultWhat it is for
SITE_URLhttp://localhost:5173Used to build links inside emails and jobs. Keep it identical to the web Worker's value.
ADMIN_EMAILadmin@nextbase.localThe support address in templates, and the Resend from address when MAIL_FROM is not set.
MAIL_FROMnot setOptional. When present, apps/jobs/src/handlers.ts uses it as the Resend sender, so the sender can be a verified address such as Nextbase <no-reply@example.com> while ADMIN_EMAIL stays a real mailbox. The shipped env.production block sets it.

Bindings, not variables

These are configured in the Wrangler files and are not env vars you type. Keep the binding names exactly as they are; the code depends on them.

BindingTypeUsed by
APP_DBD1 databaseWeb, admin and jobs. Must point at the same database in each environment.
PUBLIC_MEDIA, PRIVATE_MEDIAR2 bucketsWeb, admin and jobs
JOBSQueue producerWeb, admin and jobs; the jobs Worker is also the consumer with a -dlq dead-letter queue
REALTIMEDurable Object RealtimeRoomDefined in web; admin and jobs reference it through script_name
AUTH_RATE_LIMITERDurable Object AuthRateLimiterDefined in web; admin references it through script_name
CF_VERSION_METADATAWorker version metadataAll three Workers, for release IDs in logs

After changing a binding or a var, run pnpm cf:typegen to regenerate worker-configuration.d.ts in the web and jobs Workers, and pnpm --filter @nextbase/admin cf:typegen for the admin Worker, so the Env types match.

Related

  • Authentication for what BETTER_AUTH_SECRET and the provider keys turn on.
  • Deployment for the full list of wrangler secret put commands.
  • Emails with Resend for the shared email guidance.

Installation

Clone the TanStack + Cloudflare D1 starter, migrate the local D1 database, start the web, admin and jobs Workers and create your first account.

Authentication

How Better Auth, platform roles, the separate admin app and workspace capabilities protect the TanStack + Cloudflare D1 starter.

On this page

Web Worker secretsAdmin Worker secrets and local valuesJobs Worker secretsWeb Worker varsAdmin Worker varsJobs Worker varsBindings, not variablesRelated