Skip to main content

Environment Variables

UI environment config lives in:

apps/ui/.env.local
apps/ui/src/env.mjs
apps/ui/src/lib/env-vars.ts

All variables are optional in src/env.mjs: the schema uses @t3-oss/env-nextjs and intentionally allows building without secrets baked in. Runtime code must still check that required values exist where they are used.

warning

Do not leave empty values such as DATABASE_PASSWORD= in .env. Empty values are treated as set, so default config fallbacks will not be used. Remove or comment the line when you want the default.

Use getEnvVar()

Use getEnvVar() from src/lib/env-vars.ts instead of reading process.env directly. It works in server code and client code, including values injected through CSR env injection.

import { env } from "@/env.mjs"

import { getEnvVar } from "@/lib/env-vars"

// OK
console.log(getEnvVar("TEST_VARIABLE"))

// Also works, but prefer getEnvVar()
console.log(env.TEST_VARIABLE)

// Do not read process.env directly
console.log(process.env.TEST_VARIABLE)

Strapi API Tokens

Strapi API tokens authenticate UI requests to the Strapi Content API. See the official Strapi API Tokens docs.

Read-Only Token

Open Strapi admin → Settings → API Tokens, then open the seeded Read Only token and click Regenerate.

Set the generated value in:

STRAPI_REST_READONLY_API_KEY=<paste-token-here>

The regenerated token is shown once.

Custom Token

Write operations (POST, PUT, DELETE) need a Custom token:

STRAPI_REST_CUSTOM_API_KEY=<custom-token>

Create it in Strapi admin → Settings → API Tokens.

API token permissions are manual

Permissions are scoped manually per content type. Strapi currently does not provide a way to share API token permissions between environments through config files or another project-level sync mechanism.

Reference

VarScopeRequiredUsed by
APP_PUBLIC_URLserverYesCanonical URL and metadata base URL; Better Auth baseURL; URL formatting.
STRAPI_URLserverYesStrapi base URL; Strapi clients; proxy routes. Required at build if pre-rendering ISR pages.
STRAPI_REST_READONLY_API_KEYserverYesRead-only Strapi API token for public content reads; public-proxy GET/HEAD auth; server-side reads.
STRAPI_REST_CUSTOM_API_KEYserverWhen usedPublic-proxy writes (POST, PUT, DELETE).
STRAPI_PREVIEW_SECRETserverWhen usedStrapi preview route and preview listener.
BETTER_AUTH_SECRETserverWhen auth is usedEncrypts Better Auth session cookie.
BASIC_AUTH_ENABLEDserverNoEnables Basic Auth for the whole app when needed.
BASIC_AUTH_USERNAME
BASIC_AUTH_PASSWORD
serverWhen basic auth is enabledCredentials for the edge basic auth gate.
IMGPROXY_URLserverNoExternal image optimization service.
RECAPTCHA_SECRET_KEYserverWhen reCAPTCHA is usedreCAPTCHA v3 verification.
SENTRY_AUTH_TOKEN
SENTRY_ORG
SENTRY_PROJECT
serverWhen source maps are uploadedSentry source-map upload at build time.
SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNINGserverNoSuppresses Sentry global error handler file warnings.
DEBUG_STATIC_PARAMS_GENERATIONserverNoStatic params generation debug logging.
DEBUG_STRAPI_CLIENT_API_CALLSserverNoVerbose Strapi client logging.
SHOW_NON_BLOCKING_ERRORSserverNoLogs non-blocking runtime errors.
NEXT_OUTPUTserverNoKeep undefined for local development, set to standalone for Docker builds, or export for static builds. See Docker Build and Next Configuration.
NEXT_PUBLIC_SENTRY_DSNclientWhen Sentry is usedSentry browser SDK.
NEXT_PUBLIC_RECAPTCHA_SITE_KEYclientWhen reCAPTCHA is usedreCAPTCHA widget.
NEXT_PUBLIC_PREVENT_UNUSED_FUNCTIONS_ERROR_LOGSclientNoSentry noise filter.
NODE_ENVsharedNoStandard Node.js environment mode. In this project it is development or production.
APP_ENVsharedNoProject deployment environment label. Used when the app needs to distinguish deployments such as testing and production independently from NODE_ENV.

Environment Helpers

Use the helpers from src/lib/general-helpers.ts when code needs to branch by environment:

HelperReadsReturns true when
isProduction()APP_ENVAPP_ENV is production.
isTesting()APP_ENVAPP_ENV is testing.
isDevelopment()NODE_ENVNODE_ENV is development.

Use APP_ENV for deployment-specific behavior such as production-only SEO output or testing deployments. Use NODE_ENV for framework/runtime mode checks such as local development behavior.

CSR Env Injection

CSR env injection lets the client/browser read selected environment values without rebuilding the whole frontend when those values change. In Docker, this also lets a single image serve multiple environments.

Prefer CSR injection for runtime public config

For public values that only need to be read by the browser at runtime, CSR env injection can avoid adding NEXT_PUBLIC_* variables that are baked into the frontend bundle during build.

The root layout reads selected env vars on the server and injects them into:

window.CSR_CONFIG

getEnvVar() reads from window.CSR_CONFIG on the client. Configure the allowlist via CSR_ENVs in:

apps/ui/src/app/[locale]/layout.tsx
Never inject secrets

window.CSR_CONFIG is serialized into the HTML response and is visible to anyone who views source or opens DevTools.

Only include values that are safe to publish: public API base URLs, GA/Sentry public DSNs, feature flags, or environment labels.

Never include API keys, JWTs, database URLs, Strapi STRAPI_REST_*_API_KEY values, OAuth client secrets, or any token that grants server-side access.