Environment variables
Every variable in the starter's two example env files, which runtime reads it, and where its value comes from.
The kit has two example files: .env.local.example at the repository root (Convex CLI and the web app) and apps/admin/.env.local.example (the admin app). Three different places read these variables, and that is the main thing to get right.
- Web browser bundle (public): variables prefixed
VITE_in the root.env.localare inlined into the web bundle by Vite at build time, becauseapps/web/vite.config.tssetsenvDir: "../..". Never put a secret in aVITE_variable. - Admin browser bundle (public): the admin app reads its own
apps/admin/.env.local(envDir: "."). The root file does not reach it. - Convex deployment (server-only): everything without a
VITE_prefix is read by Convex functions withprocess.env. A value in.env.localdoes not reach the backend. Set it in the selected deployment withpnpm convex env set NAME value, or in the Convex dashboard.
Both .env.local files are gitignored. In the root file, CONVEX_DEPLOYMENT, VITE_CONVEX_URL and CONVEX_SITE_URL are maintained by pnpm db:local:select (or pnpm convex deployment select); everything else is yours. If the CLI creates the file from scratch it writes CONVEX_URL instead of VITE_CONVEX_URL, so copy the example first (see installation).
Placeholders only
The values in the example files (re_example, sk_test_example, whsec_example, admin@example.com) are placeholders. Replace them with your own and never commit real keys.
Deployment selection and URLs
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
CONVEX_DEPLOYMENT | Convex CLI, dev:local guard | Required | Selected deployment, for example local:nextbase or prod:<name> | Written by pnpm db:local:select or pnpm convex deployment select |
VITE_CONVEX_URL | Web browser, dev:local guard | Required | Convex functions URL the web app connects to | http://127.0.0.1:3210 locally; https://<name>.convex.cloud in production (Convex dashboard, Settings > URL & Deploy Key). Written by the CLI when the line already exists |
CONVEX_SITE_URL | Convex deployment | Required | Origin of HTTP actions, including /mcp/*, /oauth/* and /api/*; also used by auth.config.ts as the JWT domain | http://127.0.0.1:3211 locally; https://<name>.convex.site in production. Convex supplies it in cloud deployments |
APP_URL | Convex deployment | Required | Public origin of the web app, used to build links in app emails and as a fallback consent-page origin for MCP | http://localhost:3000 locally; your HTTPS origin in production. Must be an absolute URL without credentials, HTTPS outside localhost. Never generated |
Authentication and email
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
NEXTBASE_ADMIN_EMAIL | Convex deployment | Required for admin | The one signed-in account allowed to claim platform admin on the admin app's /app-admin | Your own address |
AUTH_RESEND_KEY | Convex deployment | Needed for sign-up | Resend API key used by Convex Auth for verification codes, password reset and magic links. Sign-up cannot complete without it | Resend dashboard |
AUTH_EMAIL_FROM | Convex deployment | Needed for sign-up | Sender for auth emails, for example Nextbase <auth@example.com> | A verified Resend domain |
RESEND_API_KEY | Convex deployment | Optional | Dedicated key for app emails (invitations, email change codes, deletion confirmation). Falls back to AUTH_RESEND_KEY | Resend dashboard |
EMAIL_FROM | Convex deployment | Optional | Sender for app emails. Falls back to AUTH_EMAIL_FROM | A verified Resend domain |
EMAIL_CHANGE_SECRET | Convex deployment | Required | Hashes email-change verification codes | Generate at least 32 random characters |
SITE_URL | Convex deployment | Set by auth:setup | Convex Auth's site URL (the web origin): the first allowed redirect origin, the base for password reset links and a consent-page fallback | Written by pnpm auth:setup; set it to your production web origin when deploying |
ADMIN_SITE_URL | Convex deployment | Required for the admin app | Origin of the admin app. Added to the auth redirect allowlist so admin login, OAuth and magic link callbacks return to the admin origin; admin MCP consent is routed here | http://localhost:3002 locally; your admin HTTPS origin in production. Listed as a comment in the root example |
JWT_PRIVATE_KEY, JWKS | Convex deployment | Set by auth:setup | Convex Auth signing keys | Generated by pnpm auth:setup. Not in the example file; never paste them into a frontend env |
Social login
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
VITE_OAUTH_PROVIDERS | Web browser, admin browser | Optional | Comma-separated list of buttons to show: google,github,twitter. Providers not listed are hidden. Set it in both env files if the admin app should show the buttons too | Your choice |
AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET | Convex deployment | Optional | Google OAuth credentials | Google Cloud console |
AUTH_GITHUB_ID, AUTH_GITHUB_SECRET | Convex deployment | Optional | GitHub OAuth credentials | GitHub developer settings |
AUTH_TWITTER_ID, AUTH_TWITTER_SECRET | Convex deployment | Optional | Twitter OAuth credentials | Twitter developer portal |
Showing a button with VITE_OAUTH_PROVIDERS does not configure the provider. Its AUTH_* credentials must be set in the deployment too.
Billing, AI and analytics
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
STRIPE_SECRET_KEY | Convex deployment | Optional | Stripe API access for billing | Stripe dashboard |
STRIPE_WEBHOOK_SECRET | Convex deployment | Optional | Verifies signatures on POST /api/stripe/webhook | Stripe webhook endpoint settings |
OPENAI_API_KEY | Convex deployment | Optional | Upstream key for POST /api/ai/stream | OpenAI dashboard |
OPENAI_ALLOWED_MODELS | Convex deployment | Optional | Comma-separated allowlist for the streaming endpoint; defaults to gpt-5-mini | Your choice |
VITE_POSTHOG_KEY | Web browser | Optional | Enables PostHog capture; leave unset to disable | PostHog project settings |
VITE_POSTHOG_HOST | Web browser | Optional | PostHog host, default https://us.i.posthog.com | PostHog project settings |
Separate admin app and MCP
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
VITE_ADMIN_APP_URL | Web browser | Required | Origin of the admin app. The web app uses it to hand admin MCP consent requests to the admin app and to return from an impersonation session | http://localhost:3002 locally; your admin origin in production |
MCP_APP_URL | Convex deployment | Optional | Canonical web origin for the user /mcp/authorize consent page and the MCP browser origin allowlist. Falls back to APP_URL, then SITE_URL | Your web origin |
Admin app file (apps/admin/.env.local.example)
| Variable | Where it is read | Required | Purpose | Where to get the value |
|---|---|---|---|---|
VITE_CONVEX_URL | Admin browser | Required | The same Convex functions URL the web app uses | http://127.0.0.1:3210 locally; https://<name>.convex.cloud in production. The example ships a cloud placeholder |
VITE_WEB_APP_URL | Admin browser | Required | Customer web origin. Target of impersonation handoffs (/auth/impersonate) and the "Open web app" link. The admin app throws if it is missing when you impersonate, and requires HTTPS outside localhost | http://localhost:3000 locally; your web origin in production |
VITE_OAUTH_PROVIDERS | Admin browser | Optional | Social buttons on the admin login page, same format as the web app | Your choice |
Build-time variables on Vercel
turbo.json lists VITE_CONVEX_URL, VITE_OAUTH_PROVIDERS, VITE_POSTHOG_HOST, VITE_POSTHOG_KEY, VITE_WEB_APP_URL and VITE_ADMIN_APP_URL as inputs to the build task. The committed vercel.json builds the frontend only and does not run convex deploy, so set VITE_CONVEX_URL and VITE_ADMIN_APP_URL (plus any optional VITE_ values) by hand in the web Vercel project, and VITE_CONVEX_URL and VITE_WEB_APP_URL in the admin Vercel project. CONVEX_DEPLOY_KEY is only needed if you change the build command to run convex deploy. The deployment page has the details.
Installation
Run the TanStack + Convex starter locally with the Convex local backend, Convex Auth, the web app and the admin app.
Authentication
How Convex Auth works in the TanStack + Convex starter, including verification emails, social login, sessions, the separate admin app, the admin claim flow and impersonation.