Environment configuration
Configure core URLs, secrets, feature flags, and optional providers safely.
The checked-in .env.example file is the source of truth for supported buyer configuration. Copy it to .env.local for development and configure the same names in your deployment platform for production.
cp .env.example .env.local.env.local and other local environment files are ignored by Git. Never commit them.
Public and server-only values
Variables beginning with NEXT_PUBLIC_ can be embedded in browser JavaScript. Use them only for public URLs, publishable IDs, and feature flags.
Keep database credentials, provider secret keys, webhook secrets, SMTP passwords, and BETTER_AUTH_SECRET in server-only variables. Never add NEXT_PUBLIC_ to a secret to make it available to client code.
Core local configuration
A functional local email-auth baseline uses:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vibeany
BETTER_AUTH_SECRET=<generated-secret>
NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_ENABLE_EMAIL_AUTH=true
NEXT_PUBLIC_ENABLE_PAYMENTS=falseGenerate the auth secret instead of inventing a memorable value:
openssl rand -base64 32Leave BETTER_AUTH_URL unset during ordinary local development. Better Auth then follows the actual localhost origin, including a non-default port. Set it to the canonical HTTPS origin in production or when a fixed preview or tunnel callback requires one.
Configuration groups
URLs and presentation
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_SITE_URL | Metadata, canonical URLs, sitemap entries, and public links. |
NEXT_PUBLIC_APP_URL | Application callback and return URL base. |
BETTER_AUTH_URL | Optional server-side canonical auth origin; required only when automatic resolution is unsuitable. |
NEXT_PUBLIC_BRAND_NAME | Optional deployment-specific display-name override. |
NEXT_PUBLIC_BRAND_WORDMARK_ACCENT | Optional accented suffix in the rendered wordmark. |
Use the same production origin for the site, app, and auth URLs unless you have deliberately designed and tested a split-domain deployment.
Authentication and email
| Capability | Variables |
|---|---|
| Email and password | NEXT_PUBLIC_ENABLE_EMAIL_AUTH, BETTER_AUTH_SECRET |
| Google OAuth | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
| Google One Tap | Google variables plus NEXT_PUBLIC_GOOGLE_CLIENT_ID, NEXT_PUBLIC_ENABLE_ONE_TAP |
| Signup Turnstile | NEXT_PUBLIC_TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY |
| Resend | RESEND_API_KEY, RESEND_FROM_EMAIL |
| SMTP | SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, RESEND_FROM_EMAIL |
| Administrator allowlist and contact recipients | ADMIN_EMAILS |
Turnstile keys must be configured as a pair. Do not enable One Tap without the server Google credentials and the public client ID. Every address in ADMIN_EMAILS receives administrator authorization as well as contact notifications, so include only controlled admin accounts.
Payments
Set NEXT_PUBLIC_ENABLE_PAYMENTS=true only after one complete provider configuration exists. PAYMENTS_PROVIDER must be exactly stripe or creem; there is no implicit fallback.
New checkout and webhook traffic use the selected provider. Existing subscriptions retain the provider stored with them for cancellation and portal operations. Changing the switch does not migrate live subscriptions.
Provider credentials, webhook secrets, product or price IDs, CRON_SECRET, and the configurable subscription refund threshold are documented with the payment flow. Keep every secret server-side.
Optional product capabilities
| Capability | Main variables |
|---|---|
| AI image generation | NEXT_PUBLIC_ENABLE_IMAGE_GENERATION, optional IMAGE_PROVIDER, and one of FAL_KEY, MODELSCOPE_API_KEY, DASHSCOPE_API_KEY |
| Object storage | STORAGE_PROVIDER, S3_ENDPOINT, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET_NAME, optional region/public URL |
| Analytics | NEXT_PUBLIC_GA_ID, NEXT_PUBLIC_CLARITY_ID |
| Legal acceptance | NEXT_PUBLIC_TERMS_VERSION, NEXT_PUBLIC_PRIVACY_VERSION |
Keep optional features disabled until their provider is configured and tested. The UI and API gates are designed to agree on these flags.
Reserved development variables
The environment schema contains names for purchase diagnostics, self-grant, manual grant, verbose logging, and development warnings. Some are reserved or presentation-only and are not consumed by every runtime path. In particular, ALLOW_MANUAL_GRANT is not an authorization boundary for the admin credit-adjustment API. Privileged access is enforced by server-side authentication and the ADMIN_EMAILS allowlist. Treat a flag as a real production control only after the corresponding server route and tests prove that behavior.
Boolean flags
The shared feature-flag parser accepts values such as true, 1, on, enabled, and yes. Use lowercase true or false consistently in project and deployment configuration to make reviews unambiguous.
Production configuration
Set production values in the deployment platform rather than copying .env.local. At minimum, production requires a reachable database, a strong auth secret, a non-localhost HTTPS origin, and at least one tested sign-in method.
If email auth is enabled, production also needs either:
RESEND_API_KEYplus a validRESEND_FROM_EMAIL, or- the complete SMTP host, port, user, password set plus
RESEND_FROM_EMAIL.
After configuring the real production URL and enabled capabilities, run:
npm run preflightPreflight checks core variables, enabled providers, database connectivity, migration safety, and TypeScript. It intentionally fails when NEXT_PUBLIC_SITE_URL still points to localhost, so it is a production-readiness check rather than a local-dev health signal.
For machine-readable, redacted output:
npm run --silent preflight -- --jsonChanges require a restart
Next.js reads server variables at process start, and public variables can be embedded during a build. Restart npm run dev after changing .env.local, and create a new deployment after changing production variables.
Continue with Authentication and email or return to the Quickstart.