All documents

MERIDIAN · DOC 19 / 25

Environment

Every environment variable, public vs secret, local vs production principles.

One template: .env.example (committed, placeholders only). Real values live in .env (git-ignored) or the deployment secret store.


1 · The golden rule

Anything prefixed NEXT_PUBLIC_ is compiled into the browser bundle and visible to every visitor. Never place secrets in a public variable.

Server-only variables never get the prefix and are only read inside src/server/** or src/db/**.


2 · Variable reference

Server-only (secret)

VariablePurposeExample / placeholder
MONGODB_URIMongoDB connection string (Mongoose ODM)mongodb://127.0.0.1:27017/meridian (local) · mongodb+srv://USER:PASSWORD@cluster0.example.mongodb.net/meridian (Atlas)
SESSION_SECRETreserved for cookie-value signing / CSRF derivation. Phase 3 sessions are opaque random tokens hashed at rest — set this anyway for the layers that will need itreplace_with_secure_random_value
PLATFORM_HOST_SUFFIXEScomma-separated extra host suffixes that serve the PLATFORM surface only (previews/staging). Tenants never resolve through them. While NEXT_PUBLIC_PLATFORM_DOMAIN is still the placeholder, the managed preview host suffix is auto-includedempty (production)
LOG_LEVELpino level: trace/debug/info/warn/error/fatalinfo

Public (non-secret, shipped to browsers)

VariablePurposeExample
NEXT_PUBLIC_APP_URLabsolute origin for links/SEOhttp://localhost:3000
NEXT_PUBLIC_API_BASE_URLAPI base path for the browser client/api/v1
NEXT_PUBLIC_PLATFORM_DOMAINplatform domain (subdomains)nttrack.com

3 · Where values are read

Code locationVariables
src/db/index.tsMONGODB_URI
src/server/config/env.tsall server-only vars (validated, typed)
src/services/api-client.tsNEXT_PUBLIC_API_BASE_URL

Config is loaded through src/server/config/env.ts — modules import typed config, never process.env scattered through business code.


4 · Local development

cp .env.example .env
# MONGODB_URI defaults to a local mongod instance

No wildcard subdomains locally in Phase 1 → the app runs on localhost; tenant host-resolution is documented for Phase 4 (docs/architecture.md §2).

5 · Production variable table (deployment reference)

VariableScopeSensitive?Production value
NODE_ENVservernoproduction (set by PM2 ecosystem too)
PORTserverno3000 behind Nginx — never public
MONGODB_URIserverYESAtlas mongodb+srv://… least-privilege user
SESSION_SECRETserverYESopenssl rand -hex 32 (rotate deliberately)
LOG_LEVELservernowarn
GEOCODING_BASE_URLservernolicensed/self-hosted instance recommended
GEOCODING_USER_AGENTservernoidentified UA incl. contact
GEOCODING_CONTACTservernoops contact (forwarded to Nominatim policy)
PLATFORM_HOST_SUFFIXESservernoEMPTY in production (previews only)
NEXT_PUBLIC_APP_URLpublic bundlenohttps://nttrack.com
NEXT_PUBLIC_API_BASE_URLpublic bundleno/api/v1 (same-origin)
NEXT_PUBLIC_PLATFORM_DOMAINpublic bundlenonttrack.com — drives tenant links AND host resolution
NEXT_PUBLIC_OSM_TILE_URLpublic bundlenotile template URL

Cookies: intentionally NO COOKIE_DOMAIN variable — cookies are host-only (narrowest scope; docs/deployment.md §cookies). Tenant identity comes from the Host header + NEXT_PUBLIC_PLATFORM_DOMAIN, never from client-supplied tenant hints.

5 · Production principles