How to Create Custom Environments in Angular (Step-by-Step Guide)

Technogic profile picture By Technogic
Thumbnail image for How to Create Custom Environments in Angular (Step-by-Step Guide)

Introduction

When building Angular applications, it’s common to need different configurations for different stages of your project — such as development, testing, staging, or production. Each environment might require distinct API endpoints, feature toggles, logging levels, or analytics settings. Managing these differences efficiently is crucial to ensure smooth development and deployment workflows.

Angular provides a built-in environment mechanism that allows developers to define environment-specific configurations and automatically swap them during build time. This means you can maintain clean, maintainable code while easily targeting different environments with simple CLI commands.

In this tutorial, we’ll explore Angular’s built-in environment system in detail and learn how to create custom environments using it. We’ll see how Angular handles environment files internally through file replacement, how to configure them in angular.json, and how to serve or build your app using those environments.

We’ll keep things simple and focused — this post will not cover advanced or runtime-based configuration techniques (such as loading .env files or dynamic JSON at runtime). Instead, we’ll stick to Angular’s native, compile-time mechanism, which remains the most common and reliable way to manage multiple environments in modern Angular projects.

By the end, you’ll understand how to set up a clean environment structure, add your own custom environment (like “staging” or “QA”), and use it effectively in your Angular application.

Default Environment Setup

Angular provides a built-in mechanism for handling different environments, such as development, testing, and production. This feature allows developers to maintain separate configuration files and automatically switch between them during the build process. In the latest versions of Angular (v17+), the default setup has been streamlined, focusing on simplicity and maintainability.

The Default Environment Files

When you create a new Angular project using the Angular CLI (ng new), it automatically generates two environment files inside the src/environments directory:

src/
└── environments/
    ├── environment.ts
    └── environment.development.ts

Each file represents a specific environment configuration:

  • environment.ts — This acts as the default environment file.

  • environment.development.ts — This is specifically for development builds.

This is a change from older Angular versions (prior to v15), where you would typically find both environment.ts and environment.prod.ts. The shift reflects Angular’s move toward a simpler, more flexible environment configuration system.

Default File Content

Here’s what the default files generally look like:

environment.ts

export const environment = {
  appName: 'my-angular-app'
};

environment.development.ts

export const environment = {
  appName: 'my-angular-app (Development)'
};

Notice that the default setup no longer includes a production flag. This change encourages developers to rely on Angular’s built-in tools for determining runtime mode rather than maintaining a manual boolean flag.

How Angular Uses These Files

Angular uses file replacements during the build process to substitute environment-specific files. The mappings are defined in your project’s angular.json file under the build configurations. For example:

"configurations": {
  "development": {
    "buildOptimizer": false,
    "optimization": false,
    "sourceMap": true,
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.development.ts"
      }
    ]
  },
  "production": {
    "buildOptimizer": true,
    "optimization": true
  }
}

When you run:

ng build --configuration=development

Angular automatically replaces environment.ts with environment.development.ts during the build process.

Checking Development Mode in Angular

In previous Angular versions, developers often used environment.production to determine whether the app was running in production. However, as of recent versions, Angular recommends using the isDevMode() function instead.

You can import it directly from @angular/core:

import { isDevMode } from '@angular/core';

if (isDevMode()) {
  console.log('Running in development mode');
}

This method ensures your app correctly identifies the environment without relying on a custom variable, keeping your configuration clean and consistent with Angular’s internal behavior.

Summary

To summarize:

  • The latest Angular versions generate two environment files by default: environment.ts and environment.development.ts.

  • The production variable is no longer a default part of the configuration.

  • The Angular CLI automatically handles file replacements based on build configurations.

  • To detect whether your app is running in development mode, you should use isDevMode() from @angular/core.

This modern approach provides a cleaner and more consistent way to handle environment-based configurations while aligning closely with Angular’s internal runtime detection mechanisms.

Creating a Custom Environment (Beyond “development”)

While Angular’s default environment setup provides just two configurations — the base environment.ts and environment.development.ts — real-world projects often need more flexibility. For instance, you might want different environments for staging, testing, QA, or UAT (User Acceptance Testing). Thankfully, Angular makes it simple to define your own custom environments and integrate them into your build process.

Let’s walk through the entire process step-by-step.

Step 1: Create a New Environment File

Start by creating a new file for your custom environment inside the src/environments directory. For example, let’s create a staging environment:

src/
└── environments/
    ├── environment.ts
    ├── environment.development.ts
    └── environment.staging.ts

Now, open environment.staging.ts and add your environment-specific settings. For example:

export const environment = {
  apiUrl: 'https://staging.api.myapp.com',
  featureFlags: {
    enableNewUI: true
  },
  appVersion: '1.0.0-staging'
};

This file contains all configuration details specific to your staging setup — perhaps pointing to a staging backend server or enabling certain features for pre-release testing.

Step 2: Add File Replacement in angular.json

Next, you need to tell Angular when to use this new environment file. To do that, open your project’s angular.json and locate the "build" section inside the "architect" configuration. You’ll see something like this:

"configurations": {
  "development": {
    "buildOptimizer": false,
    "optimization": false,
    "sourceMap": true,
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.development.ts"
      }
    ]
  },
  "production": {
    "buildOptimizer": true,
    "optimization": true
  }
}

Now, add a new entry for the staging configuration:

"staging": {
  "buildOptimizer": true,
  "optimization": true,
  "sourceMap": false,
  "fileReplacements": [
    {
      "replace": "src/environments/environment.ts",
      "with": "src/environments/environment.staging.ts"
    }
  ]
}

This tells Angular:

Whenever I build with the staging configuration, replace environment.ts with environment.staging.ts.

Step 3: Create a Staging Build Command

Once you’ve defined the configuration, you can create a build command for it. For example:

ng build --configuration=staging

This command compiles your Angular app using the staging configuration, automatically swapping out the environment file for environment.staging.ts.

You can also add a shortcut in your package.json scripts section for convenience:

"scripts": {
  "build:staging": "ng build --configuration=staging"
}

Now, you can simply run:

npm run build:staging

Step 4: Using Environment Variables in Your Code

To use your environment variables anywhere in your Angular app, import them from the environment module:

import { environment } from '../environments/environment';

console.log('API URL:', environment.apiUrl);

Angular’s file replacement system ensures that, depending on the build configuration, this import points to the correct environment file — whether it’s environment.development.ts, environment.staging.ts, or the default environment.ts.

Step 5: Verifying the Build

To confirm that your environment replacement works correctly, build the project with your new configuration:

ng build --configuration=staging

After the build completes, open the generated files in the dist/ folder and inspect your environment variables (for example, using browser dev tools or console logs). You should see the staging-specific configuration values.

Best Practices for Custom Environments

  • Keep configurations minimal: Only include values that differ between environments.

  • Avoid sensitive data: Never store secrets or API keys directly in environment files — use secure environment management or backend configuration instead.

  • Maintain consistency: Ensure every environment file exports an object with the same structure to prevent runtime errors.

  • Document your environments: Especially in large teams, it’s helpful to document what each environment represents and how to build for it.

Summary

Creating custom environments in Angular is straightforward:

  1. Add a new environment file under src/environments/.

  2. Register it in angular.json under the build configurations.

  3. Build using ng build --configuration=<your-env>.

This flexible setup allows you to manage different stages of your app lifecycle — from development and staging to production — without cluttering your code or manually toggling variables.

Conclusion

Managing multiple environments is a vital part of any professional Angular workflow, and the framework’s built-in environment mechanism makes this process clean, scalable, and easy to maintain.

In the latest Angular versions, the simplified setup with just environment.ts and environment.development.ts offers a modern foundation for environment-based configurations. From there, extending your setup to include custom environments—like staging, QA, or testing—is straightforward through Angular’s powerful file replacement system defined in angular.json.

By keeping configurations lightweight, using consistent structure across files, and leveraging Angular’s native isDevMode() for development detection, you ensure your project remains both flexible and future-proof.

With this approach, you gain precise control over how your app behaves in each stage of its lifecycle—whether you’re debugging locally, testing in staging, or deploying to production—without introducing unnecessary complexity.