How to Generate Cloud Builds in React Native Expo
Technology Blogs

How to Generate Cloud Builds in React Native Expo

Aharta Dudhe
Associate Software Engineer

Building React Native apps for Android and iOS usually means installing Xcode, Android Studio, and juggling signing certificates and keystores. EAS (Expo Application Services) Build moves that work to the cloud: you run a single command, and Expo’s servers produce installable builds for you. No local native toolchain is required for standard builds, and credentials are managed securely in one place.

Why use cloud builds?
You get consistent, reproducible builds without maintaining local SDKs or signing setup. Teammates and CI pipelines can trigger builds from any machine. EAS runs your build on dedicated workers (including macOS for iOS), so you don’t need a Mac for iOS builds. This guide walks you through the prerequisites, then the full Android and iOS processes so you can ship builds reliably without exposing keys or secrets.

Prerequisites: Setting Up Your Environment

Before you trigger any cloud build, a few foundations need to be in place. Skipping these often leads to failed builds or credential prompts mid-flow.

1. Node.js and Package Manager

Use Node.js v18 or later (LTS is recommended for stability). EAS CLI works with npm, yarn, or Bun pick whatever your project already uses. Run `node –version` to confirm. If your team uses a specific Node version, consider a version manager (e.g. nvm) so everyone matches.

Why it matters: The EAS build worker uses a fixed Node version on the server; your local Node version mainly affects running the CLI and scripts. Mismatched Node versions can cause “works on my machine” issues when build scripts or native tooling run differently locally vs in the cloud.

2. Expo SDK and EAS CLI

Your project must be an Expo app (managed workflow or with `expo prebuild`). Install or run EAS CLI via your package manager so the version matches what your project expects:

```bash

npx eas-cli --version

 or: bunx eas --version

```

Check the `cli.version` field in your `eas.json` (e.g. `”>= 16.6.1″`). If the installed CLI is older, update it or adjust the constraint so EAS Build accepts your config.

Tip: Pin the CLI version in `eas.json` so that everyone (and CI) uses the same EAS CLI version. That reduces surprises when new CLI releases change behavior or add required fields.

3. Expo Account and Login

Sign up at [expo.dev](https://expo.dev) and log in from the CLI. EAS ties every build to your account and project:

```bash

npx eas login

```

Without this, the first `eas build` will prompt you to authenticate. For CI/CD, use token-based auth as described in Expo’s docs never commit or log credentials.

Linking a project: The first time you run `eas build`, you’ll be asked to create or link an EAS project. Linking associates your repo with a project on expo.dev so builds, credentials, and OTA updates are scoped to that project. All team members should use the same linked project for shared credentials and build history.

4. Project Configuration: app.config and eas.json

Two files drive how EAS Build behaves.

`app.config.js` or `app.config.ts`  holds your Expo app config: `name`, `slug`, `version`, and platform blocks for `ios` and `android`. For EAS you need:

– `extra.eas.projectId` — Set when you first run `eas build` or link the project in the dashboard. It identifies your project for builds and OTA updates.

– `updates.url` — If you use OTA updates, point this to `https://u.expo.dev/<projectId>` so the app knows where to fetch updates.

– Sensitive values — Never hard code API URLs, OAuth client IDs, or tokens. Use environment variables (e.g. `process.env.EXPO_PUBLIC_API_URL`) and supply real values via EAS Secrets or a local `.env` that is not committed.

`eas.json` defines build profiles. Each profile is a named set of options:

– `distribution` — `”internal”` for ad-hoc/internal installs (Android: APK/AAB via link; iOS: ad-hoc or enterprise). Omit or use `”store”` for Play Store / App Store.

– `environment` — EAS “environments” (e.g. `development`, `preview`, `production`) determine which set of EAS Secrets is injected. Create environments in the Expo dashboard and assign secrets to them.

– `channel` — Used by Expo Updates (OTA). The built app checks this channel for over-the-air updates; point each profile to the right channel so preview builds don’t receive production updates.

– `autoIncrement` — When `true`, EAS bumps the Android version code and/or iOS build number automatically so each build is uniquely versioned without editing config.

– Platform overrides — Under `ios` or `android` you can set options like `ios.simulator: true` (simulator-only iOS build) or `android.buildType: “apk”` (default is AAB for store).

Example structure without any secrets:

```json

{

  "cli": { "version": ">= 16.6.1" },

  "build": {

    "development": {

      "developmentClient": true,

      "distribution": "internal",

      "environment": "development",

      "channel": "development"

    },

    "preview": {

      "distribution": "internal",

      "environment": "preview",

      "autoIncrement": true,

      "channel": "preview"

    },

    "production": {

      "environment": "production",

      "autoIncrement": true,

      "channel": "production"

    }

  }

}

```

5. Environment Variables and EAS Secrets

For local development, use a `.env` file and keep it in `.gitignore`. Load variables in `app.config` and in your app so that `EXPO_PUBLIC_*` vars are available at build time.

For EAS cloud builds, use EAS Secrets. They are injected during the build according to the profile’s `environment`. Create them via CLI or the Expo dashboard:

```bash

npx eas secret:create --scope project --name EXPO_PUBLIC_API_URL --value "https://api.example.com/v1/graphql"

npx eas secret:list

```

In `app.config`, read via `process.env.EXPO_PUBLIC_*`. Never commit real keys or tokens only placeholders in docs and real values in EAS Secrets or local `.env`.

Scope and naming: Secrets can be scoped to the project (`–scope project`) or to an environment. Names must match what your app and `app.config` expect (e.g. `EXPO_PUBLIC_API_URL`). Variables prefixed with `EXPO_PUBLIC_` are exposed to the client bundle; use them only for non-sensitive config (e.g. API base URL). Truly secret values (e.g. API secrets) should not use `EXPO_PUBLIC_` and should be used only in server-side or build-time logic if needed.

6. Git and Repo State

EAS Build uses your git repository (or a linked GitHub/GitLab integration). You can optionally include uncommitted changes when starting a build, but for reproducible builds and clear history, commit and push first. That way each build maps to a known commit.

What gets built: By default EAS builds from the current git state (including uncommitted files if you choose). If you use GitHub/GitLab integration, you can trigger builds from a branch or commit. The build logs and the Expo dashboard show the commit SHA so you can always trace a build back to source.

Need Help Scaling Your React Native Builds? Talk To Our Mobile Experts.

What Happens When You Run a Build?

When you run `eas build`, the CLI uploads your project (or a tarball of it) to EAS. A build worker then:

  1. Checks out your code (or uses the uploaded snapshot).
  2. Installs dependencies (`npm install` / `yarn` / `bun install`).
  3. Injects EAS Secrets for the profile’s `environment`.
  4. Runs prebuild if needed (generates native `ios/` and `android/` from your Expo config).
  5. Builds the native app (e.g. `xcodebuild` for iOS, Gradle for Android) and signs it with the credentials stored in EAS.
  6. Uploads the artifact (IPA, APK, or AAB) and provides a link.

Build time varies (often 10–25 minutes depending on platform and cache). You can watch logs in the terminal or on the build page. Caching is enabled by default so dependency install and native build steps are faster on subsequent runs.

Process: Android Cloud Builds

1. Android Config in app.config

In your Expo config, the `android` section must define at least:

– `package` — Your application ID (e.g. `com.yourcompany.yourapp`). It must be unique and consistent for store submissions.

– `adaptiveIcon` (or `icon`) — So the launcher shows a proper icon. Adaptive icons (foreground + background) improve appearance across launchers.

You can also set `versionCode` in the config, or leave it to EAS and use `autoIncrement` in the build profile. Do not put keystores or signing keys in the repo; EAS will create or use stored credentials when you build.

Output format: For store builds, EAS produces an AAB (Android App Bundle) by default, which is required for Play Store. For internal testing you may get an APK or AAB depending on profile; you can force APK with `”android”: { “buildType”: “apk” }` in the profile if needed for older tooling.

2. Build Profiles for Android

Use different profiles for different goals. Preview (or similar) with `distribution: “internal”` is for internal testing; production is for Play Store. Set `environment` so the right EAS Secrets are applied. Optionally use `autoIncrement` so each build gets a new version code without editing config.

3. First-Time Credentials

When you run your first Android build, EAS will ask about credentials if none exist. Prefer letting EAS generate and store a keystore; it is then reused for all future builds. Alternatively you can upload your own keystore and set the password as a secret. Configure or inspect credentials later in the [Expo dashboard](https://expo.dev) under your project → Credentials → Android. Never commit keystores or passwords.

If you already have a Play Store keystore: You can upload it to EAS so that updates to an existing app are signed with the same key. Losing the keystore for a published app can prevent you from ever updating it on the Play Store, so backing it up and/or using EAS to manage it is important.

4. Running an Android Build

From the project root:

“`bash

npx eas build –platform android –profile development   # dev client

npx eas build –platform android –profile preview       # internal

npx eas build –platform android –profile production   # Play Store

Use `–platform all` to build Android and iOS in one go. The CLI prints a link to the build page; you can also open Builds in the Expo dashboard.

Useful flags: `–non-interactive` for CI (no prompts); `–clear-cache` if you suspect a cache issue; `–local` to run the build on your machine instead of EAS (requires Android SDK/Studio locally). You can also pass `–message “Release 1.2.3″` to attach a message to the build for your team.

5. After the Build

Builds run on Expo’s servers. Link to the build page is printed in the terminal; you can also open [expo.dev](https://expo.dev) → your project → Builds. For internal distribution, EAS provides a link or QR code to download the APK or AAB. For production, download the AAB and upload it to Google Play Console, or run:

```bash

npx eas submit --platform android --profile production

```

Configure the submit profile in `eas.json` under `submit` if you need custom options (e.g. track, rollout fraction). Google Play: For first-time submission you still need to create the app in Play Console and complete store listing; EAS Submit uploads the AAB and can optionally promote to a track (internal, alpha, beta, production).

Process: iOS Cloud Builds

1. iOS Config in app.config

The `ios` block should include:

– `bundleIdentifier` — Must match the app you create in App Store Connect (e.g. `com.yourcompany.yourapp`).

– `buildNumber` — Can be managed by EAS when `autoIncrement` is enabled in the build profile.

Add any Apple-specific options (e.g. `usesAppleSignIn`, `infoPlist`). Keep sensitive values in env vars and EAS Secrets, not in the repo.

Simulator vs device: A simulator build runs only in the iOS Simulator (no Apple Developer account or provisioning needed for the build itself). It’s useful for CI, automated tests, or quick checks without a device. Device builds (development, preview, production) require an Apple Developer account and proper provisioning; EAS can generate and store the required certificates and profiles for you.

2. Build Profiles for iOS

Use a simulator profile (e.g. `ios.simulator: true`) for fast, device-free testing; preview for internal device testing; production for App Store. Same idea as Android: `distribution` and `environment` control who can install the build and which secrets are injected.

3. First-Time Setup: Apple Developer and Credentials

You need an Apple Developer Program membership ($99/year). In App Store Connect, create the app and set the bundle ID to match `app.config`. When you run your first iOS build, EAS will prompt for your Apple ID and can generate and store distribution certificates and provisioning profiles. For internal builds it uses ad-hoc or development provisioning; for production it uses a distribution certificate and App Store profile. You can also upload your own credentials. Manage them in the Expo dashboard under Credentials → iOS. Never commit certificates or provisioning profiles.

Provisioning in brief: Development and ad-hoc profiles are tied to specific device UDIDs. For internal distribution, testers must register their devices (EAS can help via `eas device:create`). App Store distribution uses a single distribution profile and does not require per-device registration.

4. Running an iOS Build

From the project root:

```bash

npx eas build --platform ios --profile ios-simulator   # simulator only

npx eas build --platform ios --profile development    # dev client (device)

npx eas build --platform ios --profile preview        # internal

npx eas build --platform ios --profile production     # App Store

```

iOS builds run on macOS workers in the cloud. Progress and logs are on the build page. Simulator builds are typically faster than device builds because they skip code signing and provisioning steps.

5. After the Build

For simulator builds, download the artifact and install it in the iOS Simulator. For internal distribution, EAS gives a link; testers may need their device UDIDs registered in the Apple Developer portal—you can use `eas device:create` to simplify that. For production, download the IPA and upload to App Store Connect or run:

```bash

npx eas submit --platform ios --profile production

```

App Store Connect: Ensure the app record exists in App Store Connect with the correct bundle ID. EAS Submit uploads the IPA and can optionally submit for TestFlight or App Store review; you can also upload the IPA manually from the build page.

Tips and Troubleshooting

– Build fails with “missing environment variable”: Ensure the profile’s `environment` has the required EAS Secrets set. Run `eas secret:list` and add any missing vars with `eas secret:create`.

– iOS build fails on credentials: In the dashboard, check Credentials → iOS. Delete invalid or expired certs and let EAS regenerate, or upload your own.

– Android build fails on signing: Confirm the keystore (and alias/password if you uploaded your own) are set correctly under Credentials → Android.

– Slow or flaky builds: Use `–clear-cache` sparingly; usually caching helps. If dependencies or native code change often, consider splitting rarely changed layers so cache hits more often.

– Reproducibility: Always tag or note the git commit (or branch) when sharing a build link; the build page shows the commit so you can match it to source.

coma

Conclusion

Expo EAS simplifies the complexity of building React Native apps by moving the entire build and signing process to the cloud. With a consistent setup across Android and iOS—covering prerequisites, credential management, and build commands—teams can generate reliable builds without maintaining local environments or handling sensitive files manually. Whether you’re creating internal test builds or preparing for store releases, EAS provides a unified, scalable workflow that reduces friction and improves release velocity.

By leveraging EAS Secrets and environment-based configurations, you also ensure that sensitive data remains secure while keeping builds reproducible across teams and CI pipelines. This approach not only minimizes operational overhead but also enables faster, more predictable deployments—making it easier to scale your mobile development process with confidence.

Aharta Dudhe

Aharta Dudhe

Associate Software Engineer

Aharta is a passionate React Native developer. He have proficiency in technologies like React Native, Android, MySQL, alsohe is dedicated to continuously improving his skills and delivering high-quality, efficient solutions.

Share This Blog

Read More Similar Blogs

Let’s Transform
Healthcare,
Together.

Partner with us to design, build, and scale digital solutions that drive better outcomes.

Location

5900 Balcones Dr, Ste 100-7286, Austin, TX 78731, United States

Contact form