Environment Variables

Configure environment variables and connect services for the Next.js template.

Architecture note: This page's Web configuration applies to the standalone product. A Unified Platform Host also applies the native-origin, OAuth-audience, App API, webhook, storage, and notification boundaries in Server Configuration.

Configuration lives in .env (copied from .env.example). This page is the reference for every variable the template reads, grouped by service. Each is marked:

  • Required (core) — the app will not start or core auth breaks without it.
  • Required (feature) — needed only if you use that feature.
  • Optional — has a default or only changes behavior.

Server secrets vs. public values. Variables prefixed with NEXT_PUBLIC_ are inlined into the browser bundle at build time and are visible to users — never put secrets there. Everything else is server-only. Because NEXT_PUBLIC_* values are fixed at build, changing them requires a rebuild.

Core

VariableRequiredNotes
DATABASE_URLRequired (core)PostgreSQL connection string, e.g. postgresql://user:password@localhost:5432/soar_next.

Better Auth

VariableRequiredNotes
BETTER_AUTH_SECRETRequired (core)Secret used to sign sessions. Generate with openssl rand -base64 32. Keep it stable; changing it invalidates sessions.
BETTER_AUTH_URLRequired (core)Base URL of the app. http://localhost:3000 locally; your canonical HTTPS URL in production.

Better Auth reads these from the environment automatically — they are not passed through process.env in src/lib/auth.ts. See Authentication.

OAuth providers

Both providers are optional. If you don't configure one, hide its button rather than leaving a non-functional control — see Authentication.

VariableRequiredNotes
GITHUB_CLIENT_IDRequired (feature)GitHub OAuth app client ID.
GITHUB_CLIENT_SECRETRequired (feature)GitHub OAuth app secret.
GOOGLE_CLIENT_IDRequired (feature)Google OAuth client ID.
GOOGLE_CLIENT_SECRETRequired (feature)Google OAuth client secret.

Creem payments

VariableRequiredNotes
CREEM_SERVER_IDXOptionalSelects the Creem server (sandbox vs. live). Defaults to 0 when unset (src/lib/payment/creem.ts).
CREEM_API_KEYRequired (feature)Creem API key for creating checkouts.
CREEM_WEBHOOK_SECRETRequired (feature)Verifies incoming webhook signatures.
NEXT_PUBLIC_CREEM_PRODUCT_PRO_MONTHLYRequired (feature)Public Creem product ID for the Pro monthly plan. Build-time, exposed to the browser.
NEXT_PUBLIC_CREEM_PRODUCT_PRO_YEARLYRequired (feature)Public Creem product ID for the Pro yearly plan.
NEXT_PUBLIC_CREEM_PRODUCT_LIFETIMERequired (feature)Public Creem product ID for the Lifetime plan.

These map the Free / Pro / Lifetime pricing plans to Creem products; they are distinct from the display prices in src/config/price-config.ts. See Payments.

Resend email

VariableRequiredNotes
RESEND_API_KEYRequired (feature)Resend API key. Needed for email verification, password reset, and the contact form. Without it, email verification blocks login.

The sender and support addresses are set in src/config/website-config.ts (fromEmail, supportEmail), not via env. See Email.

OpenAI (AI chat)

VariableRequiredNotes
OPENAI_API_KEYRequired (feature)Used by the streaming chat route. The OpenAI SDK reads it from the environment automatically. See AI Chat.

Replicate (AI media)

VariableRequiredNotes
REPLICATE_API_TOKENRequired (feature)Used by the image/video/audio generation routes. The Replicate SDK reads it automatically. See AI Media.

Native & mobile clients

Needed only when a native client (e.g. the SoarStarter Swift template in Unified Mode) runs against this backend — see Native Authentication.

VariableRequiredNotes
APP_SCHEMERequired (feature)Your app's URL scheme (e.g. soar://). Native clients send it as their Origin; it is the only extra origin trusted in production.
DEV_TRUSTED_ORIGINSOptionalComma-separated extra trusted origins, honored only in development.
GOOGLE_IOS_CLIENT_IDRequired (feature)Google iOS client ID accepted as an ID-token audience.
GOOGLE_ANDROID_CLIENT_IDRequired (feature)Google Android client ID accepted as an ID-token audience.
APPLE_APP_BUNDLE_IDENTIFIERRequired (feature)iOS bundle ID. Registers native Apple sign-in and validates the ID token's audience. No Services ID or client secret needed.

RevenueCat (App Store purchases)

Syncs App Store purchases into the shared subscription row — see Cross-Platform Subscriptions.

VariableRequiredNotes
REVENUECAT_WEBHOOK_AUTHORIZATIONRequired (feature)Full Authorization header value the webhook must receive (e.g. Bearer rc_whsec…). Configure the identical value in the RevenueCat dashboard.
REVENUECAT_PRODUCT_PRO_MONTHLYRequired (feature)App Store product ID mapped to the Pro monthly plan.
REVENUECAT_PRODUCT_PRO_YEARLYRequired (feature)App Store product ID mapped to the Pro yearly plan.
REVENUECAT_PRODUCT_LIFETIMERequired (feature)App Store product ID mapped to the Lifetime plan.

App API & object storage

See Object Storage & Direct Uploads.

VariableRequiredNotes
SOAR_APP_BASE_URLOptionalPublic base URL of this app; used to build local upload URLs in development. Defaults suit http://localhost:3000.
STORAGE_PROVIDERRequired (core)local (development only — refused in production) or r2.
R2_ACCOUNT_IDRequired (feature)Cloudflare account ID (when STORAGE_PROVIDER=r2).
R2_ACCESS_KEY_IDRequired (feature)R2 API token key ID.
R2_SECRET_ACCESS_KEYRequired (feature)R2 API token secret.
R2_BUCKETRequired (feature)Bucket name for uploads.
R2_PUBLIC_BASE_URLRequired (feature)Public base (custom domain or r2.dev) used to build object URLs.

APNs (push notifications)

Used by the authenticated test-push endpoint — see Push Notifications. Server-only secrets.

VariableRequiredNotes
APNS_TEAM_IDRequired (feature)Apple Developer team ID.
APNS_KEY_IDRequired (feature)Key ID of the APNs Auth Key (.p8).
APNS_BUNDLE_IDRequired (feature)App bundle ID, sent as the apns-topic.
APNS_PRIVATE_KEYRequired (feature)Contents of the .p8 key; \n escapes are supported so it fits on one line.

Site & demo

VariableRequiredNotes
NEXT_PUBLIC_SITE_URLOptionalCanonical site URL used for metadataBase in src/app/[locale]/layout.tsx and the marketing page. Falls back to https://soarstarter.com if unset. Public, build-time.
NEXT_PUBLIC_IS_DEMOOptionalWhen "true", toggles demo behavior in the dashboard sidebar (src/config/user-sidebar-config.ts). Public, build-time.

Both NEXT_PUBLIC_SITE_URL and NEXT_PUBLIC_IS_DEMO are read by the app but are not in .env.example — add them yourself. Set NEXT_PUBLIC_SITE_URL to your real domain in production so Open Graph and canonical metadata resolve correctly; otherwise it falls back to the SoarStarter default. Leave NEXT_PUBLIC_IS_DEMO unset (or any value other than "true") for normal behavior.

Local vs. production

  • Local: BETTER_AUTH_URL=http://localhost:3000, a local or dev database, and CREEM_SERVER_IDX pointed at sandbox.
  • Production: your canonical HTTPS BETTER_AUTH_URL and NEXT_PUBLIC_SITE_URL, a hosted database with pooling, live Creem server and product IDs, a verified Resend domain, and a fresh BETTER_AUTH_SECRET. Remember that NEXT_PUBLIC_* changes require a rebuild. See Deployment.

On this page