Configuration
The repo is easiest to maintain when each file owns one lane or one class of configuration.
File ownership matrix
| File | Owns | Does not own |
|---|---|---|
.env.local | app/local secrets and app runtime values for the local-app lane | local Wrangler-only vars, preview/prod tenant identity |
.dev.vars.dev | local Wrangler vars for the local-worker lane | app-lane defaults, preview/prod secrets |
.env.cloudflare / .env.cloudflare.preview | remote helper, seeding, and Cloudflare API credentials | checked-in deployment identity |
wrangler.toml | tracked template-safe baseline and local-development config | private preview/prod tenant IDs and routes |
wrangler.remote.toml | private preview/prod Cloudflare tenant config | local-only development defaults |
Bootstrap wrangler.remote.toml from the committed wrangler.remote.example.toml.
Typed env layer
Application runtime values are validated through @t3-oss/env-nextjs. The canonical typed entrypoint is src/env.ts, which composes the domain schemas under src/env/*.
That means the normal workflow for new variables is:
- Add the variable to the right schema file under
src/env/. - Re-export it through
src/env.ts. - Decide which ownership file should carry the value by default.
- Update the matching example file.
Use direct process.env access only where raw process access is genuinely required, such as CLI scripts or runtime bridges.
local-app example
APP_URL="http://localhost:3101"
AUTH_SECRET="replace-me-with-a-local-secret"
DATABASE_URL="file:./dev.db"
XADMIN_SECRET="replace-me-for-local-seeding"This lane is the canonical Next.js + Playwright development lane.
local-worker example
Copy .dev.vars.example to .dev.vars.dev and keep the local Wrangler URL on port 8787:
APP_URL="http://localhost:8787"
AUTH_SECRET="replace-me-with-a-local-worker-secret"
XADMIN_SECRET="replace-me-for-local-worker-seeding"
CRON_SECRET="replace-me-for-local-worker-cron"
TRIGGER_SECRET="replace-me-for-local-worker-triggers"Keep .env.local on the app lane even if you also use Wrangler locally.
Remote helper example
Use .env.cloudflare for production helper flows and .env.cloudflare.preview for preview helper flows:
CLOUDFLARE_API_TOKEN="replace-me-with-api-token"
CLOUDFLARE_D1_TOKEN="replace-me-with-d1-or-api-token"
APP_URL="https://your-app.example.com"
XADMIN_SECRET="replace-me-with-remote-admin-secret"These files are for helper credentials and remote script inputs. They are not where preview or production account IDs, routes, or binding IDs should live.
Cloudflare config files
wrangler.toml- tracked
- template-safe baseline
- local-development defaults
wrangler.remote.toml- untracked
- private preview and production tenant identity
- bootstrapped from
wrangler.remote.example.toml
In other words: do not directly edit tracked wrangler.toml with live tenant IDs for preview or production.
Ports and URLs
local-app:http://localhost:3101local-worker:http://localhost:8787remote-cloudflare: whatever domain or route you place in private remote config
Keep those lane URLs explicit. Do not reuse one APP_URL value for all three lanes.
Common optional env groups
OAuth providers
AUTH_GITHUB_ID="your-github-client-id"
AUTH_GITHUB_SECRET="your-github-client-secret"
AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_SECRET="your-google-client-secret"
AUTH_DISCORD_ID="your-discord-client-id"
AUTH_DISCORD_SECRET="your-discord-client-secret"Payments
PAYMENT_PROVIDER="mock"
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USER="smtp-user"
SMTP_PASS="smtp-pass"
SMTP_FROM="Product <no-reply@example.com>"Analytics
NEXT_PUBLIC_POSTHOG_KEY="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://app.posthog.com"What not to do
- Do not replace
.env.localwith a generic.envworkflow for normal local development. - Do not put local Wrangler vars in
.env.local. - Do not store remote tenant identity in tracked
wrangler.toml. - Do not treat
.env.cloudflare*as a deployment identity file.
Database note
After schema changes, generate and apply migrations:
npm run db:generate
npm run db:pushNext Steps
After configuration, learn about:
- Deployment - Deploy to production
- Authentication Guide - Set up authentication
- Database Guide - Work with your database