Leave Localhost logoLeave LocalhostDocs

Environment Variables

The repo uses separate environment files for the product app, marketing site, documentation site, and Convex backend.

The repo uses separate environment files for the product app, marketing site, documentation site, and Convex backend.

apps/app/.env
apps/marketing/.env
apps/docs/.env
packages/backend/.env

Each workspace has an .env.example file. Copy those examples during setup and fill only the integrations you plan to use.

Runtime Boundary

Next.js apps read their local .env files at build and runtime.

packages/config/src/brand.ts contains static browser-safe product identity. Customize that source file for the product name, labels, logo alt text, GitHub URL, support email, and default copy. Runtime URLs remain in the environment schema of the deployable that owns them.

Convex functions do not read packages/backend/.env after deployment. Backend variables must also be set in the Convex dashboard or with the Convex CLI:

bun --cwd packages/backend convex env set NAME "value"

Keep local .env files out of git.

Product App

File: apps/app/.env

Required:

NEXT_PUBLIC_CONVEX_URL=
NEXT_PUBLIC_CONVEX_SITE_URL=
NEXT_PUBLIC_APP_URL=http://localhost:3000

Optional:

NEXT_PUBLIC_DOCS_URL=http://localhost:3004
NEXT_PUBLIC_AUTH_MICROSOFT_ENABLED=
NEXT_PUBLIC_ANALYTICS_ENABLED=
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN=
NEXT_PUBLIC_POSTHOG_HOST=
NEXT_PUBLIC_SENTRY_DSN=
SENTRY_AUTH_TOKEN=
SENTRY_ORG=
SENTRY_PROJECT=

Notes:

  • NEXT_PUBLIC_CONVEX_URL is the Convex client URL.
  • NEXT_PUBLIC_DOCS_URL is optional: when set, it owns the product app's sidebar and user-menu documentation links (http://localhost:3004 locally, your docs domain in production). Leave it unset to hide those links entirely. It can point anywhere — the bundled docs app, a hosted docs site, or a GitHub README — so shipping apps/docs is not required.
  • NEXT_PUBLIC_CONVEX_SITE_URL is the Convex HTTP actions URL used by auth.
  • NEXT_PUBLIC_APP_URL is the product app's canonical metadata URL as well as its auth client/callback URL. Use http://localhost:3000 locally and your app URL in production.
  • Static branding is configured in packages/config/src/brand.ts, not through an app runtime environment variable. Keep backend APP_NAME aligned with the brand name for auth and email consistency.
  • Only set NEXT_PUBLIC_AUTH_MICROSOFT_ENABLED=true after backend Microsoft credentials are configured.

Marketing Site

File: apps/marketing/.env

The marketing site does not use Convex. Every value is public and has a local default, so the site builds and runs out of the box; set production values before launch. Its contract lives in packages/env/src/marketing.ts and is re-exported from apps/marketing/src/env.schema.ts: src/env.ts feeds that schema to t3-env at build time, and bun check-env runs the same schema, so runtime and the doctor validate it identically.

NEXT_PUBLIC_SITE_URL=http://localhost:3002
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_DOCS_URL=http://localhost:3004
NEXT_PUBLIC_PURCHASE_URL=
NEXT_PUBLIC_ANALYTICS_ENABLED=
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN=
NEXT_PUBLIC_POSTHOG_HOST=

Notes:

  • NEXT_PUBLIC_SITE_URL is the canonical marketing URL (metadata base, canonical links, sitemap, robots). Use your marketing domain in production.
  • NEXT_PUBLIC_APP_URL is the "View demo" / app destination behind every CTA.
  • NEXT_PUBLIC_DOCS_URL is the documentation site link.
  • NEXT_PUBLIC_PURCHASE_URL is the optional checkout URL. Until it is set, purchase CTAs render a "coming soon" state instead of dead links.
  • Analytics is optional and disabled by default.

Documentation Site

File: apps/docs/.env

Every value is public and has a local default, so the docs site builds and runs out of the box. Its contract lives in packages/env/src/docs.ts and is re-exported from apps/docs/src/env.schema.ts: src/env.ts feeds it to t3-env at build time, and bun check-env runs the same schema.

NEXT_PUBLIC_DOCS_URL=http://localhost:3004
NEXT_PUBLIC_SITE_URL=http://localhost:3002

Notes:

  • apps/docs renders the repository root docs/ directory with Fumadocs and has no Convex dependency, so it needs no Convex variables.
  • NEXT_PUBLIC_DOCS_URL is the docs site's own canonical URL — it sets metadataBase and every canonical/OpenGraph URL. Use http://localhost:3004 locally and your docs domain (for example https://docs.leavelocalhost.com) in production. A fresh build no longer falls back to a docs.example.com placeholder.
  • NEXT_PUBLIC_SITE_URL is the external marketing site, rendered as the "Marketing site" navbar link. It is not the docs' own canonical URL.
  • Static branding (app name, logo, GitHub URL) still comes from @leavelocalhost/config as build-time defaults, so it is not part of this validated schema.

Backend

File: packages/backend/.env

Required for the core app:

APP_NAME=Acme App
CONVEX_SITE_URL=
SITE_URL=
BETTER_AUTH_SECRET=
AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
RESEND_API_KEY=
RESEND_AUTH_FROM_EMAIL=

Common optional values:

AUTH_TRUSTED_ORIGINS=
RESEND_FROM_EMAIL=
RESEND_WEBHOOK_SECRET=
AUTH_MICROSOFT_ID=
AUTH_MICROSOFT_SECRET=
AUTH_MICROSOFT_TENANT_ID=
ANALYTICS_ENABLED=
POSTHOG_COMPONENT_ENABLED=
POSTHOG_PROJECT_TOKEN=
POSTHOG_HOST=

Analytics (PostHog) is optional and disabled by default. Set ANALYTICS_ENABLED=true, POSTHOG_COMPONENT_ENABLED=true, and POSTHOG_PROJECT_TOKEN to enable backend events. The component flag and token must also be available to the process that runs convex dev or convex deploy. See Analytics (PostHog).

Platform super admin (optional — see Super Admin Access):

SUPER_ADMIN_EMAILS=
SUPER_ADMIN_REQUIRE_2FA=
  • SUPER_ADMIN_EMAILS — comma-separated allow-list of emails that may open the /admin panel. Leave blank to disable the admin panel entirely (no one is a super admin).
  • SUPER_ADMIN_REQUIRE_2FAtrue or false. Defaults to true when unset: an allow-listed user must also have Better Auth two-factor enabled. Set to false only for local development.

Billing selector:

BILLING_PROVIDER=

Supported values:

  • polar
  • stripe
  • lemon_squeezy

Leave BILLING_PROVIDER unset until you want billing validation and billing provider setup to become active.

Billing Provider Variables

Polar:

POLAR_ORGANIZATION_TOKEN=
POLAR_SERVER=sandbox
POLAR_WEBHOOK_SECRET=
POLAR_PRO_MONTHLY_PRODUCT_ID=
POLAR_PRO_YEARLY_PRODUCT_ID=
POLAR_PRO_LIFETIME_PRODUCT_ID=

Stripe:

STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRO_MONTHLY_PRICE_ID=
STRIPE_PRO_YEARLY_PRICE_ID=
STRIPE_PRO_LIFETIME_PRICE_ID=

Lemon Squeezy:

LEMON_SQUEEZY_API_KEY=
LEMON_SQUEEZY_STORE_ID=
LEMON_SQUEEZY_WEBHOOK_SECRET=
LEMON_SQUEEZY_TEST_MODE=true
LEMON_SQUEEZY_PRO_MONTHLY_VARIANT_ID=
LEMON_SQUEEZY_PRO_YEARLY_VARIANT_ID=
LEMON_SQUEEZY_PRO_LIFETIME_VARIANT_ID=

Local Versus Production Values

Local URLs usually look like:

NEXT_PUBLIC_APP_URL=http://localhost:3000
SITE_URL=http://localhost:3000

Convex URLs come from the Convex dashboard:

NEXT_PUBLIC_CONVEX_URL=https://your-project.convex.cloud
NEXT_PUBLIC_CONVEX_SITE_URL=https://your-project.convex.site
CONVEX_SITE_URL=https://your-project.convex.site

Production URLs should use the real deployed app domain, not localhost.

APP_NAME is required because Better Auth uses it as the application name and TOTP issuer. It also feeds sensitive-action email subjects and sender fallback names. Do not leave it blank in production.

Validation

Run:

bun check-env

Use release mode before launch:

bun check-env --release

See Setup Doctor for the full command reference.

On this page