react-monorepo environment
Each app has its own .env (generation copies each apps/*/.env.example). The
four files are the same apart from PORT, and landing adds two variables.
apps/admin/.env.example
| Variable | What to set |
|---|---|
VITE_APP_API_URL | Backend base URL. Better Auth lives at ${VITE_APP_API_URL}/auth. Production: The API's public URL, as a build argument. Compiled into the bundle. Auth lives at<this>/auth, and requests to it carry the traceparent header. |
VITE_APP_LANDING | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The landing site's origin, e.g. |
VITE_APP_AUTH_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The auth app's origin, e.g. <this>/login. |
VITE_APP_CLIENT_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The client app's origin, e.g. |
VITE_APP_ADMIN_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The admin app's origin, e.g. |
PORT | This app's own dev port. Production: Not used: each app's image serves on port 80. Each app's dev server port (landing 3000, auth 3001, client 3002, admin 3003). Change one and update the siblingVITE_APP_*_HOST values. |
VITE_OPENOBSERVE_URL | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: Your OpenObserve instance, as a build argument. Telemetry is on only when the URL, org and client token are all set. |
VITE_OPENOBSERVE_ORG | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: The project's organization identifier, as a build argument. |
VITE_OPENOBSERVE_CLIENT_TOKEN | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: A RUM token, as a build argument. Where to get it: OpenObserve → Ingestion → RUM. Public by design (write-only). Never the back ends' ingestion token. The instance must list this origin inZO_CORS_ALLOWED_ORIGINS. |
apps/auth/.env.example
| Variable | What to set |
|---|---|
VITE_APP_API_URL | Backend base URL. Better Auth lives at ${VITE_APP_API_URL}/auth. Production: The API's public URL, as a build argument. Compiled into the bundle. Auth lives at<this>/auth, and requests to it carry the traceparent header. |
VITE_APP_LANDING | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The landing site's origin, e.g. |
VITE_APP_AUTH_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The auth app's origin, e.g. <this>/login. |
VITE_APP_CLIENT_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The client app's origin, e.g. |
VITE_APP_ADMIN_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The admin app's origin, e.g. |
PORT | This app's own dev port. Production: Not used: each app's image serves on port 80. Each app's dev server port (landing 3000, auth 3001, client 3002, admin 3003). Change one and update the siblingVITE_APP_*_HOST values. |
VITE_OPENOBSERVE_URL | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: Your OpenObserve instance, as a build argument. Telemetry is on only when the URL, org and client token are all set. |
VITE_OPENOBSERVE_ORG | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: The project's organization identifier, as a build argument. |
VITE_OPENOBSERVE_CLIENT_TOKEN | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: A RUM token, as a build argument. Where to get it: OpenObserve → Ingestion → RUM. Public by design (write-only). Never the back ends' ingestion token. The instance must list this origin inZO_CORS_ALLOWED_ORIGINS. |
apps/client/.env.example
| Variable | What to set |
|---|---|
VITE_APP_API_URL | Backend base URL. Better Auth lives at ${VITE_APP_API_URL}/auth. Production: The API's public URL, as a build argument. Compiled into the bundle. Auth lives at<this>/auth, and requests to it carry the traceparent header. |
VITE_APP_LANDING | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The landing site's origin, e.g. |
VITE_APP_AUTH_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The auth app's origin, e.g. <this>/login. |
VITE_APP_CLIENT_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The client app's origin, e.g. |
VITE_APP_ADMIN_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The admin app's origin, e.g. |
PORT | This app's own dev port. Production: Not used: each app's image serves on port 80. Each app's dev server port (landing 3000, auth 3001, client 3002, admin 3003). Change one and update the siblingVITE_APP_*_HOST values. |
VITE_OPENOBSERVE_URL | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: Your OpenObserve instance, as a build argument. Telemetry is on only when the URL, org and client token are all set. |
VITE_OPENOBSERVE_ORG | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: The project's organization identifier, as a build argument. |
VITE_OPENOBSERVE_CLIENT_TOKEN | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: A RUM token, as a build argument. Where to get it: OpenObserve → Ingestion → RUM. Public by design (write-only). Never the back ends' ingestion token. The instance must list this origin inZO_CORS_ALLOWED_ORIGINS. |
apps/landing/.env.example
| Variable | What to set |
|---|---|
VITE_APP_API_URL | Backend base URL. Better Auth lives at ${VITE_APP_API_URL}/auth. Production: The API's public URL, as a build argument. Compiled into the bundle. Auth lives at<this>/auth, and requests to it carry the traceparent header. |
VITE_APP_LANDING | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The landing site's origin, e.g. |
VITE_APP_AUTH_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The auth app's origin, e.g. <this>/login. |
VITE_APP_CLIENT_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The client app's origin, e.g. |
VITE_APP_ADMIN_HOST | Sibling app origins. All four share one session cookie across subdomains, so these must agree with the backend's BETTER_AUTH_COOKIE_DOMAIN and its trustedOrigins list, or login will appear to succeed and then bounce. Production: The admin app's origin, e.g. |
PORT | This app's own dev port. Production: Not used: each app's image serves on port 80. Each app's dev server port (landing 3000, auth 3001, client 3002, admin 3003). Change one and update the siblingVITE_APP_*_HOST values. |
VITE_APP_SITE_URL | Canonical public URL, used for sitemap/robots/OG tags at build time. Production: The canonical public origin, as a build argument. Must equalPRODUCTION_ORIGIN in src/features/seo/routes.ts; any other value builds as noindex with a disallowing robots.txt, so previews can't outrank production. |
VITE_APP_SUPPORT_EMAIL | Canonical public URL, used for sitemap/robots/OG tags at build time. Production: A monitored security and support address, as a build argument. Published in/.well-known/security.txt; empty skips the file. |
VITE_OPENOBSERVE_URL | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: Your OpenObserve instance, as a build argument. Telemetry is on only when the URL, org and client token are all set. |
VITE_OPENOBSERVE_ORG | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: The project's organization identifier, as a build argument. |
VITE_OPENOBSERVE_CLIENT_TOKEN | OpenObserve browser monitoring (RUM): page views, errors, slow requests, and trace headers on API calls. Leave empty and it stays off. The client token is a RUM token (OpenObserve → Ingestion → RUM): write-only and meant to ship in the bundle — never the backend's ingestion token. The instance must list this app's origin in ZO_CORS_ALLOWED_ORIGINS. Production: A RUM token, as a build argument. Where to get it: OpenObserve → Ingestion → RUM. Public by design (write-only). Never the back ends' ingestion token. The instance must list this origin inZO_CORS_ALLOWED_ORIGINS. |
Not in any .env.example
Section titled “Not in any .env.example”| Variable | Where | Effect |
|---|---|---|
VITE_APP_ALLOWED_HOSTS |
any apps/*/.env |
Comma-separated hostnames the dev server answers beyond localhost (a tunnel, *.lvh.me) |
API_DOC_URL, API_DOC_USER, API_DOC_PASSWORD |
packages/types/.env |
Where yarn workspace @scope/types gen fetches the OpenAPI document; create this file by hand (or with its secrets script) |
INFISICAL_PROJECT_ID, INFISICAL_PATH_PREFIX |
shell | yarn secrets: each workspace pulls from <prefix>/<app> (default prefix /frontend) |
What the API must mirror
Section titled “What the API must mirror”| API setting | Must include |
|---|---|
BETTER_AUTH_COOKIE_DOMAIN |
a parent domain of every app’s host (.example.com) |
FRONTEND_HOST, MISC_CORS_ORIGINS |
every app’s origin (trusted origins and CORS) |
SMTP_SUPPORT_EMAIL |
the same address as landing’s VITE_APP_SUPPORT_EMAIL |
better-auth at /auth |
VITE_APP_API_URL + /auth |