---
modificationDate: March 09, 2026
title: Configure multiple app variants
description: Learn how to configure dynamic app config to install multiple app variants on a single device.
---

<AgentInstructions>

## Submitting Feedback

If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:

curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/tutorial/eas/multiple-app-variants/","feedback":"🤖 Agent feedback: <specific, actionable description>"}'

Only submit when you have something specific and actionable to report.

</AgentInstructions>

# Configure multiple app variants

Learn how to configure dynamic app config to install multiple app variants on a single device.

> For the complete documentation index, see [llms.txt](/llms.txt). Use this file to discover all available pages.

In this chapter, we'll configure our project to run multiple build types (development, preview, production) on a single device simultaneously. This setup will allow us to test various stages of our app development without the need to uninstall and reinstall different versions.

[Watch: How to configure multiple app variants](https://www.youtube.com/watch?v=UtJJCAfrjIg) — Configure development, preview, and production app variants with unique bundle identifiers to run them side by side on one device.

Each variant requires a unique Android Application ID and iOS Bundle Identifier to enable simultaneous installations on one device. Here's how the IDs are set up in our **app.json** file:

```json
{
  "ios": {
    "bundleIdentifier": "com.yourname.stickersmash"
    ... 
  },
  "android": {
    "package": "com.yourname.stickersmash"
    ... 
  }
}
```

## Add app.config.js for dynamic configuration

**app.json** contains app-related configuration in a JSON file. It's static and isn't ideal if we want to use [dynamic values for certain properties](/workflow/configuration#dynamic-configuration). We're going to add different Android Application IDs and iOS Bundle Identifiers for all build profiles based on [environment variables](/workflow/configuration#switching-configuration-based-on-the-environment).

-   In the root of your project, create a new file called **app.config.js**.
-   In **app.config.js**, export a default function that takes `config` as its argument. We'll then destructure the `config` to copy all existing properties from **app.json**.

```js
export default ({ config }) => ({
  ...config,
});
```

## Update dynamic values based on environment

To identify the build type, let's add two environment variables called `IS_DEV` and`IS_PREVIEW` for `development` and `preview` build profiles in **app.config.js**:

```js
const IS_DEV = process.env.APP_VARIANT === 'development';
const IS_PREVIEW = process.env.APP_VARIANT === 'preview';
```

Then, add two functions that dynamically change the app name, Android Application ID and iOS Bundle Identifier:

```js
const getUniqueIdentifier = () => {
  if (IS_DEV) {
    return 'com.yourname.stickersmash.dev';
  }

  if (IS_PREVIEW) {
    return 'com.yourname.stickersmash.preview';
  }

  return 'com.yourname.stickersmash';
};

const getAppName = () => {
  if (IS_DEV) {
    return 'StickerSmash (Dev)';
  }

  if (IS_PREVIEW) {
    return 'StickerSmash (Preview)';
  }

  return 'StickerSmash: Emoji Stickers';
};
```

We'll use `getAppName()` to assign dynamic `name` values for the app and `getUniqueIdentifier()` to differentiate `android.package` and `ios.bundleIdentifier` for development and preview builds:

```js
export default ({ config }) => ({
  ...config,
  name: getAppName(),
  ios: {
    ...config.ios,
    bundleIdentifier: getUniqueIdentifier(),
  },
  android: {
    ...config.android,
    package: getUniqueIdentifier(),
  },
});
```

## Configure eas.json

In **eas.json**, add the `APP_VARIANT` environment variable:

```json
{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "env": {
        "APP_VARIANT": "development"
      }
    },
    "preview": {
      "distribution": "internal",
      "env": {
        "APP_VARIANT": "preview"
      }
    }
    ... 
  }
}
```

Running `eas build --profile development` will now set `APP_VARIANT` to `development`.

> **Note**: Since we changed the Android Application ID and iOS Bundle Identifier, the EAS CLI will prompt us to generate a new Keystore for Android and a new provisioning profile for iOS. To learn more about what these steps include, see the previous chapter for more information.

Since our `ios-simulator` build profile extends `development`, this configuration is automatically applied for iOS Simulators.

## Run development server

> After builds are complete, follow the same procedure from previous chapters to install them on a device or emulator/simulator.

Since we're identifying our development build with the `APP_VARIANT` environment variable, we need to pass it to the command when starting the development server. To do this, add a `dev` script in the [`"scripts"`](https://docs.npmjs.com/cli/v10/using-npm/scripts) field of our project's **package.json**:

```json
{
  "scripts": {
    "dev": "APP_VARIANT=development npx expo start"
  }
}
```

Run the `npm run dev` command to start the development server:

```sh
npm run dev
```

This script will evaluate **app.config.js** locally and load the environment variable for the `development` profile.

Now, our development build will run on both Android and iOS, displaying the modified app name from **app.config.js**. For example, the below development build is running on an iOS Simulator. See that the app name is **StickerSmash (Dev)**:

You can now continue using **app.json** for static values and use **app.config.js** for dynamic values.

## Summary

Chapter 5: Configure multiple app variants

We successfully created **app.config.js** just for our dynamic configuration while leaving static configuration in **app.json** unchanged, added environment variables in **eas.json** to configure specific build profile, and learned how to start the development server with a custom **package.json** script.

In the next chapter, learn about what are internal distribution builds, why we need them, and how to create them.

[Next: Create and share internal distribution build](/tutorial/eas/internal-distribution-builds)
