Environments

Configure environment-specific variables for collection modules in sandbox and live environments.

Configure runtime environment handling so the same collection module can use sandbox credentials in sandbox and production credentials in live.

The same collection module artefact runs in both sandbox and live environments. There is no separate per-environment build. Instead, Root passes the current environment to the module at runtime through process.env.ENVIRONMENT.

process.env.ENVIRONMENT is the canonical environment signal. It is set to either sandbox or production.

Detect the current environment

For small cases, read process.env.ENVIRONMENT directly where you need to branch.

const isSandbox = process.env.ENVIRONMENT === 'sandbox';

For example, you can use this value when choosing whether to call a payment provider's UAT API or production API.

Centralize environment configuration

A common pattern is to create a config.ts file that reads process.env.ENVIRONMENT once and returns the correct values for the current environment. Some templates may not include this file by default, so treat it as a recommended pattern rather than a required template file.

The environment variable names in this example, such as ROOT_API_KEY_LIVE and STRIPE_SECRET_KEY_TEST, are illustrative. Use the variable names configured for your module.

type RootEnvironment = 'sandbox' | 'production';

type EnvironmentConfig = {
  rootApiKey: string;
  rootBaseUrl: string;
  stripeApiKey: string;
};

function requireEnv(name: string): string {
  const value = process.env[name];

  if (!value) {
    throw new Error(`Missing required environment variable: ${name}`);
  }

  return value;
}

const currentEnvironment = process.env.ENVIRONMENT as RootEnvironment | undefined;

if (currentEnvironment !== 'sandbox' && currentEnvironment !== 'production') {
  throw new Error("ENVIRONMENT must be either 'sandbox' or 'production'");
}

const configByEnvironment: Record<RootEnvironment, () => EnvironmentConfig> = {
  production: () => ({
    rootApiKey: requireEnv('ROOT_API_KEY_LIVE'),
    rootBaseUrl: requireEnv('ROOT_BASE_URL_LIVE'),
    stripeApiKey: requireEnv('STRIPE_SECRET_KEY_LIVE'),
  }),
  sandbox: () => ({
    rootApiKey: requireEnv('ROOT_API_KEY_SANDBOX'),
    rootBaseUrl: requireEnv('ROOT_BASE_URL_SANDBOX'),
    stripeApiKey: requireEnv('STRIPE_SECRET_KEY_TEST'),
  }),
};

export const Config = {
  environment: currentEnvironment,
  env: configByEnvironment[currentEnvironment](),
};

This keeps the environment branch in one place. The rest of your module can use Config.env without reading process.env.ENVIRONMENT directly.

Use the configured values

Use the resolved config when you initialize SDK clients or call external services.

import Stripe from 'stripe';

import { Config } from './config';

const stripeSDK = new Stripe(Config.env.stripeApiKey);

With this setup, the same collection module can run in sandbox and live while using the correct API keys, base URLs, and provider endpoints for each environment.

Test locally

When running the module locally or in unit tests, set ENVIRONMENT explicitly before loading the config.

ENVIRONMENT=sandbox npm test

Also set any environment variables referenced by your config, such as sandbox API keys or provider test credentials. If a required value is missing, the example requireEnv helper throws an error during startup so you can catch the misconfiguration early.