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.
  • Product branding is configured in packages/config/src/demo-brand.ts; the company/docs identity remains in packages/config/src/brand.ts. Keep backend APP_NAME aligned with demoProductBrand.appName for auth, TOTP, and email consistency. bun check-env --release enforces the match.
  • Only set NEXT_PUBLIC_AUTH_MICROSOFT_ENABLED=true after backend Microsoft credentials are configured.

Acme Landing Page

File: apps/landing-page/.env

NEXT_PUBLIC_SITE_URL=http://localhost:3001
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_DOCS_URL=http://localhost:3004
CONTACT_TO_EMAIL=hello@yourdomain.com
RESEND_API_KEY=
RESEND_FROM_EMAIL=Your App <hello@yourdomain.com>

Notes:

  • The three NEXT_PUBLIC_* values own the landing page's canonical URL and its links to the product and documentation apps.
  • CONTACT_TO_EMAIL is the private recipient for contact form submissions.
  • RESEND_API_KEY enables contact form delivery. Without it, the form shows a temporary-unavailable message and directs visitors to the public support address configured in packages/config/src/brand.ts.
  • RESEND_FROM_EMAIL should use a sender domain verified in Resend. When unset, the form uses Resend's development sender, which is restricted to permitted test recipients.

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_LANDING_PAGE_URL=http://localhost:3001
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 authenticated app destination.
  • NEXT_PUBLIC_LANDING_PAGE_URL is the Acme landing page — the destination behind every "View demo" CTA. The funnel goes marketing → Acme landing → Explore Acme → authentication.
  • 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
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