Skip to content

Environment Configuration

Source: omni-web-content-frontend environment patterns Services: AWS Secrets Manager, SSM Parameter Store


MFE services use a layered environment configuration approach:

LayerToolPurpose
SecretsAWS Secrets ManagerSensitive values (API tokens, CMS tokens)
ParametersSSM Parameter StoreNon-sensitive config (URLs, feature flags)
Build-timeNEXT_PUBLIC_* env varsClient-side configuration
Local dev.env.local fileDeveloper machine config

Use the provided script to pull secrets from AWS Secrets Manager into a local .env.local file:

Terminal window
# From src/ directory
bash scripts/environment-variables.sh -s next-env-vars/local

This script:

  1. Authenticates with AWS Secrets Manager
  2. Fetches the secret named next-env-vars/local
  3. Parses the JSON and writes key=value pairs to .env.local
Terminal window
bash scripts/environment-variables.sh [-p profile] [-s secret-name] [-r region] [-o output-file]
FlagDefaultPurpose
-p(account-specific)AWS CLI profile
-snext-env-vars/localSecret name in Secrets Manager
-reu-central-1AWS region
-o.env.localOutput file path
  • AWS CLI installed and configured with SSO
  • Node.js installed (for JSON parsing)
  • Access to the service’s AWS account
{
"scripts": {
"environment:set:local": "bash scripts/environment-variables.sh -s next-env-vars/local"
}
}

Available in both server and client components. Bundled into the JavaScript at build time.

VariablePurposeExample
NEXT_PUBLIC_BASE_URLCloudFront distribution URLhttps://www.hema.nl
NEXT_PUBLIC_DOMAIN_NLDutch domainhema.nl
NEXT_PUBLIC_DOMAIN_COMInternational domainhema.com
NEXT_PUBLIC_SANITY_PROJECT_IDSanity project IDabc123
NEXT_PUBLIC_SANITY_DATASETSanity datasetproduction
NEXT_PUBLIC_SANITY_STUDIO_URLSanity Studio URLhttps://studio.sanity.io/...
NEXT_PUBLIC_GTM_IDGoogle Tag Manager IDGTM-XXXXX

Only available in server components, API routes, and middleware. Never exposed to the client.

VariablePurpose
SANITY_API_READ_TOKENSanity API authentication
BASE_COMMERCE_API_URLBackend commerce API base URL
KONG_API_TOKENAPI gateway authentication
LOG_LEVELLogging verbosity (debug, info, warn, error)

Secrets are stored per environment in AWS Secrets Manager:

next-env-vars/local → Local development
next-env-vars/dev → Development environment
next-env-vars/preprod → Pre-production
next-env-vars/prod → Production

Each secret is a JSON object:

{
"NEXT_PUBLIC_BASE_URL": "https://www.hema.nl",
"NEXT_PUBLIC_SANITY_PROJECT_ID": "abc123",
"SANITY_API_READ_TOKEN": "sk-...",
"BASE_COMMERCE_API_URL": "https://api.hema.nl"
}

The runtime stack reads parameters and passes them to the ECS task definition as environment variables:

// In lib/runtime/runtime-stack.ts
const taskDefinition = new ecs.TaskDefinition(this, 'TaskDef', {
// ...
});
taskDefinition.addContainer('app', {
environment: {
NEXT_PUBLIC_BASE_URL: ssm.StringParameter.valueForStringParameter(this, '/hema/service/base-url'),
NODE_ENV: 'production',
},
secrets: {
SANITY_API_READ_TOKEN: ecs.Secret.fromSecretsManager(sanitySecret, 'SANITY_API_READ_TOKEN'),
},
});

Because Next.js bakes NEXT_PUBLIC_* variables at build time, the Dockerfile uses BuildKit secrets:

# Build-time: NEXT_PUBLIC_* vars are needed during `next build`
RUN --mount=type=secret,id=env,target=/app/.env.production \
npm run build

Runtime variables (server-only) are injected via ECS task definition environment.

See Docker/Standalone Build Guide for the full Dockerfile pattern.


For E2E testing against different environments:

.env.local → Local development
.env.dev → Dev environment E2E
.env.staging → Staging environment E2E
.env.prod → Production E2E (read-only tests)

E2E scripts reference these:

{
"e2e:bdd": "SECRETS=.env.local playwright test",
"e2e:bdd:staging": "SECRETS=.env.staging E2E_REMOTE=true playwright test"
}

  1. Add to Secrets Manager — Update the JSON secret in the appropriate environment(s)
  2. Add to .env.example — Document the variable (without real values)
  3. Add to CDK — If server-only, add to ECS task definition environment/secrets
  4. Add to Dockerfile — If NEXT_PUBLIC_*, ensure it’s available at build time
  5. Add to Vitest config — Add a test value in vitest.config.mts test.env
  6. Update documentation — Add to this guide

IssueSolution
NEXT_PUBLIC_* undefined at runtimeThese are baked at build time; rebuild the Docker image
Script fails with “Failed to retrieve secret”Check AWS SSO session is active (aws sso login)
Missing env var in deployed serviceCheck ECS task definition in CloudFormation; verify SSM/Secrets Manager path
Different values per localeUse the domain env vars (NEXT_PUBLIC_DOMAIN_NL, NEXT_PUBLIC_DOMAIN_COM)

See omni-web-content-frontend/src/:

  • scripts/environment-variables.sh — Local env setup script
  • vitest.config.mts test.env — Test environment variables
  • utils/constants.ts — Public URL and feature flag constants