Web app (frontend)

The web app has no validated env schema. Variables are read where they are used. The scripts in the root package.json wrap Turborepo with dotenv -c, which loads .env and then .env.local from the repository root. There is no .env.example in the repository at the time of writing.

Required

Optional

Build-time only

The Dockerfile and the CI workflows also set DATABASE_URL and BETTER_AUTH_SECRET to placeholder values during the build. The web app no longer opens a database connection or runs better-auth in process, so these are not needed at runtime. A local .env may still contain a DATABASE_URL from before the consolidation. It can be removed.

The boundary check

pnpm check:core-api runs tools/check-no-direct-core-api.sh. It fails when:
  • any file other than apps/saas/modules/shared/lib/core-api.ts mentions CORE_API_URL or SERVICE_AUTH_SECRET,
  • a variable named NEXT_PUBLIC_CORE_API... exists,
  • a "use client" file imports core-api or calls coreApiFetch,
  • core-api.ts is missing or does not import server-only.
At the time of writing, several other files also read CORE_API_URL: bff-proxy.ts, bff-server-fetch.ts, modules/admin/lib/admin-api.ts, and the route handlers under app/api/onboarding and app/api/waitlist. The script allows only core-api.ts, so it reports these files. CI runs the script as its first step. Either the allow list or those files need to change before the check passes.

Mobile app (mobile)

The mobile app reads only EXPO_PUBLIC_* variables at runtime. Expo inlines them into the JavaScript bundle at build time, so they are public. Never put a secret in one. mobile/.env.example is in the repository. .env and .env.production are ignored by Git.

Where the values come from in each context

Variables used only by scripts

Values that must match across repositories