# Development builds

## Introduction to development builds

Why use development builds and how to get started.

**Development build** is the term that we use for a "Debug" build of an app that includes the [`expo-dev-client`](/versions/latest/sdk/dev-client/) library. This library augments the built-in React Native development tooling with additional capabilities, such as support for inspecting network requests and a "launcher" UI that lets you switch between different development servers (such as between a server running on your machine or a teammate's machine) and deployments of your app (such as published updates with EAS Update).
Note: Difference between Expo Go and development builds
---
[Expo Go](https://expo.dev/go) is a playground app for students and learners to get started quickly. It comes with a fixed set of native libraries built in, so you can write JavaScript code and see changes instantly without building a native app yourself. A development build is a fully featured development environment for working on your production-grade Expo apps.
---
Note: Native app and JavaScript bundle
---
The **native app** is what you install on your device. Expo Go is a pre-built native app that works like a playground &mdash; it can't be changed after you install it. To add new native libraries or change things like your app name and icon, you need to build your own native app (a development build).
The **JavaScript bundle (`npx expo start`)** is where your app's UI code and business logic are. In production apps, there is one **main.js** bundle that is shipped with the app itself. In development, this JS bundle is live reloaded from your local machine. The main role of React Native is to provide a way for the JavaScript code to access the native APIs (Image, Camera, Notifications, and more). However, only APIs and libraries that were bundled in the **native app** can be used.
---
Video Tutorial: [Expo Go & Development Builds: which should you use?](https://www.youtube.com/watch?v=FdjczjkwQKE)
## Why use a development build (a.k.a what _can't_ you do in Expo Go and why)
Expo Go is a playground for students and learners to understand the basics of React Native. It's limited and not useful for building production-grade projects, so most apps will convert to using development builds. It helps to know exactly what is _impossible_ in Expo Go and _why_, so you can make an informed decision on when and why to make this move.
Note: Use libraries with native code that aren't in Expo Go
---
Consider [`react-native-webview`](/versions/latest/sdk/webview/) as an example, a library that contains native code, but [is included in Expo Go](https://github.com/expo/expo/blob/main/apps/expo-go/package.json#L23). When you run `npx expo install react-native-webview` command in your project, it will install the library in your **node_modules** directory, which includes both the JS code and the native code. But the JS bundle you are building _only_ uses the JS code. Then, your JS bundle gets uploaded to Expo Go, and it interacts with the native code that was already bundled with the app.
Instead, when you try to use a library that is not included, for example, [`react-native-firebase`](/guides/using-firebase/#using-react-native-firebase), then you can use the JS code and hot reload the new bundle into Expo Go but it will immediately error because the JS code tries to call the native code from the React Native Firebase package that does not exist in Expo Go. There is no way to get the native code into the Expo Go app unless it was already included in the bundle that was uploaded to the app stores.
---
Note: Test changes in app icon, name, splash screen
---
If you're developing your app in Expo Go only, you can build a store version that will use your provided values and images; it just won't be possible to test it in Expo Go.
These native assets are shipped with the native bundle and are immutable once the app is installed. The Expo Go app does show a splash screen, which is your app icon on a solid color background. This is a dev-only emulation to view how the splash screen will probably look. However, it is limited, for example, you cannot test `SplashScreen.setOptions` to animate the splash screen.
---
Note: Remote push notifications
---
While [in-app notifications](/versions/latest/sdk/notifications/) are available in Expo Go, remote push notifications (that is, sending a push notification from a server to the app) are not. This is because a push notification service should be tied to your own push notification certificates, and while it is possible to make it work in Expo Go, it often causes confusion for production builds. It is recommended to test remote push notifications in development builds so you can ensure parity in behavior between development and production.
---
Note: Implementing App/Universal links
---
Both [Android App Links](/linking/android-app-links/) and [iOS Universal Links](/linking/ios-universal-links/) require a two-way association between the native app and the website. In particular, it requires the native app to include the linked website's URL. This is impossible with Expo Go due to the aforementioned native code immutability.
---
Note: Open projects using older SDKs (iOS device only)
---
Expo Go can only support one SDK version at a time. When a new SDK version is released, Expo Go is updated to support the newer version, and this will be the only version of Expo Go available to install from the stores.
If you're developing on an Android Device, Android Emulator, or iOS Simulator, a compatible version of Expo Go can be [downloaded and installed](https://expo.dev/go). The only platform where this is impossible is iPhone devices because Apple does not support side-loading older versions of apps.
---


## Switch from Expo Go to a development build

How to switch from your Expo Go project to use development builds.

To switch from Expo Go to a development build, you'll need to follow the steps below:
Step 1: 
## Install the `expo-dev-client`
The Expo Dev Client library includes the launcher UI (shown in the screenshots below), dev menu, extensions to test over-the-air updates, and more. The Expo Go app has the dev menu built in, and that's why you need to install it separately for a development build.
```sh
$ npx expo install expo-dev-client
```
> We recommend using the `expo-dev-client` for the best development experience, but it is possible to use development builds without installing this library. If not using the dev client, in [Step 3](/develop/development-builds/expo-go-to-dev-build/#start-the-dev-client), start the bundler with `--dev-client`. Otherwise, it will default to opening in Expo Go.
Step 2: 
## Build your native app
With Expo Go, you only needed to build the JavaScript bundle, but with development builds you also need to compile the native app. With Expo, there are two parts to building your native app:
1. Generate the native **android** and/or **ios** directories ([read more](/develop/development-builds/expo-go-to-dev-build/#cng-and-prebuild) on when and how you'll need to do this)
2. Use native build tools to compile the native app(s)
Once you've built your native app, you won't need to build it again unless you add or update a library with native code, or change any native code or configuration, such as the app name.
> The **android** and **ios** directories are automatically added to **.gitignore** when you create a new project, so they won't be checked into Git. This ensures you can always regenerate the code locally or on CI with [CNG](/workflow/continuous-native-generation/) when needed and never have to edit native code manually.
### Option 1: Build on your local machine
To build a native app on your local machine, follow the setup your environment guides for [Android](/workflow/android-studio-emulator/) and [iOS](/workflow/ios-simulator/) platforms. This involves setting up and configuring native build tools like Android Studio for Android and Xcode for iOS.
Once you have everything set up, run the following command:
For Build for Android: 
```sh
$ npx expo run:android
```
For Build for iOS: 
```sh
$ npx expo run:ios
```
By default, this will build and install the app on an Android Emulator/iOS Simulator. If you need to run the build on your phone, plug it into your computer (on Android, select trust device and allow USB debugging if prompted, and on iOS, enable [developer mode](/get-started/set-up-your-environment/?mode=development-build&buildEnv=local&platform=ios&device=physical#plug-in-your-device-via-usb-and-enable-developer-mode)) and run the above commands with the `--device` flag.
### Option 2: Build on EAS
Building on EAS servers is useful when:
- You can't or don't want to set up your local development environment
- You want to build an iOS app but don't own a Mac
- You want to share the development builds with your team
Step 3: 
## Start the bundler
After building locally, `npx expo run:android|ios` will start the bundler automatically. But if you closed the bundler or are working on a dev client you built earlier, (re)start the Metro bundler with:
```sh
$ npx expo start
```
When your project has `expo-dev-client` installed, the bundler will print out **Using development build**, and the QR code it shows will link into the development build you created instead of Expo Go.
## Prebuild
[**Prebuild** ](/workflow/continuous-native-generation/#prebuild) is a concept unique to Expo projects. It refers to the process of generating the **android** and **ios** directories based on your local configuration and properties.
### When should you run prebuild
You will need to run prebuild locally if you are building via `npx expo run:android|ios`, and change any native dependencies or configuration, such as:
- Installing or updating a library containing native code
- Changing [app config](/workflow/configuration/)(`app.json`)
- Upgrading your Expo SDK version
In these cases, you'll want to rebuild the native directories with:
```sh
$ npx expo prebuild --clean
```
Then, rebuild your app with the updated native code, with:
For Build for Android: 
```sh
$ npx expo run:android
```
For Build for iOS: 
```sh
$ npx expo run:ios
```
### When you don't need to run prebuild
All Expo build tools (`npx expo run:android|ios` and `eas build`) will **prebuild** automatically if no existing native folders are found. This means that there is no need to run prebuild manually when you're running `npx expo run:android|ios` for the first time or `eas build`.


## Create a development build on EAS

Learn how to create development builds for a project.

When you create a new Expo app with `npx create-expo-app`, you start off with a project where you update the JavaScript code on your local machine and view the changes in the Expo Go app. A **development build** is essentially **your own version of Expo Go** where you are free to use any native libraries and change any native config. In this guide, you will learn how to convert your project that runs on Expo Go into a development build, which will make the native side of your app fully customizable.
Video Tutorial: [How to create a development build](https://www.youtube.com/watch?v=uQCE9zl3dXU)
## Prerequisites
The instructions assume you already have an existing Expo project that runs on Expo Go.
The requirements for building the native app depend on which platform you are using, which platform you are building for, and whether you want to build on EAS or on your local machine.
Note: Build on EAS
---
This is the easiest way to build your native app, as it requires no native build tools on your side. The builds happen on the EAS servers, which makes it possible to trigger iOS builds from non-macOS platforms.
|             | Android    | iOS Simulator | iPhone device   |
| ----------- | ---------- | ------------- | --------------- |
| **macOS**   | <YesIcon/> | <YesIcon/>    | <YesIcon/> (\*) |
| **Windows** | <YesIcon/> | <YesIcon/>    | <YesIcon/> (\*) |
| **Linux**   | <YesIcon/> | <YesIcon/>    | <YesIcon/> (\*) |
(\*) All builds that run on an iPhone device require a paid [Apple Developer](https://developer.apple.com) account for build signing.
---
Note: Build locally using the EAS CLI
---
Any EAS CLI command can be built on your local machine with the `--local` flag. This requires your local [development environment](https://reactnative.dev/docs/set-up-your-environment?os=macos&platform=ios) to be set up with native build tools. Read more about [local app development](/build-reference/local-builds/).
|             | Android           | iOS Simulator | iPhone device   |
| ----------- | ----------------- | ------------- | --------------- |
| **macOS**   | <YesIcon/>        | <YesIcon/>    | <YesIcon/> (\*) |
| **Windows** | <YesIcon/> (\*\*) | <NoIcon />    | <NoIcon />      |
| **Linux**   | <YesIcon/>        | <NoIcon />    | <NoIcon />      |
(\*) All builds that run on an iPhone device require a paid [Apple Developer](https://developer.apple.com) account for build signing.
(\*\*) No first-class support, but possible with [WSL](http://expo.fyi/wsl.md).
---
Note: Build locally without EAS
---
To build locally without EAS requires your local [development environment](https://reactnative.dev/docs/set-up-your-environment?os=macos&platform=ios) to be set up with native build tools. This is the only way to test your iOS build on an iPhone device without a paid Apple Developer Account (only possible on macOS). Read more about [local app compilation](/guides/local-app-development/#local-app-compilation) and see the [Expo Go to Development Build](/develop/development-builds/expo-go-to-dev-build/) guide.
|             | Android    | iOS Simulator | iPhone device |
| ----------- | ---------- | ------------- | ------------- |
| **macOS**   | <YesIcon/> | <YesIcon/>    | <YesIcon/>    |
| **Windows** | <YesIcon/> | <NoIcon />    | <NoIcon />    |
| **Linux**   | <YesIcon/> | <NoIcon />    | <NoIcon />    |
---
## Get started
For detailed, step-by-step instructions, see our [EAS Tutorial](/tutorial/eas/introduction). Available also as a [tutorial series](https://www.youtube.com/playlist?list=PLsXDmrmFV_AS14tZCBin6m9NIS_VCUKe2) on YouTube.
Step 1: 
### Install expo-dev-client
```sh
$ npx expo install expo-dev-client
```
Note: Are you using this library in a existing (bare) React Native apps?
---
Apps that don't use [Continuous Native Generation](/workflow/continuous-native-generation/) or are created with `npx react-native`, require further configuration after installing this library. See steps 1 and 2 from [Install `expo-dev-client` in an existing React Native app](/bare/install-dev-builds-in-bare/).
---
Step 2: 
### Build the native app (Android)
<Prerequisites numberOfRequirements={3}>
  <Requirement number={1} title="Expo account">
    Sign up for an [Expo](https://expo.dev/signup) account, if you haven't already.
  </Requirement>
  <Requirement number={2} title="EAS CLI">
    The [EAS CLI](/build/setup/#install-the-latest-eas-cli) installed and logged in.
    ```sh
$ npm install -g eas-cli && eas login
```
  </Requirement>
  <Requirement number={3} title="An Android Emulator (optional)">
    An [Android Emulator](/workflow/android-studio-emulator/) is optional if you want to test your
    app on an emulator.
  </Requirement>
</Prerequisites>
```sh
$ eas build --platform android --profile development
```
Read more about [Android builds on EAS](/tutorial/eas/android-development-build).
Step 2: 
### Build the native app (iOS Simulator)
<Prerequisites numberOfRequirements={3}>
  <Requirement number={1} title="Expo account">
    Sign up for an [Expo](https://expo.dev/signup) account, if you haven't already.
  </Requirement>
  <Requirement number={2} title="EAS CLI">
    The [EAS CLI](/build/setup/#install-the-latest-eas-cli) installed and logged in.
    ```sh
$ npm install -g eas-cli && eas login
```
  </Requirement>
  <Requirement number={3} title="macOS with iOS Simulator installed">
    iOS Simulators are available only on macOS. Make sure you have the [iOS
    Simulator](/workflow/ios-simulator/) installed.
  </Requirement>
</Prerequisites>
Edit `development` profile in **eas.json** and set the [`simulator`](/eas/json/#simulator) option to `true` (you have to create a separate profile for simulator builds if you also want to create iOS device builds for this project).
```json eas.json
{
  "build": {
    "development": {
      "ios": {
        "simulator": true
      }
    }
  }
}
```
```sh
$ eas build --platform ios --profile development
```
iOS Simulator builds can only be installed on simulators and not on real devices.
Read more about [iOS Simulator builds on EAS](/tutorial/eas/ios-development-build-for-simulators/).
Step 2: 
### Build the native app (iOS device)
<Prerequisites numberOfRequirements={3}>
  <Requirement number={1} title="Expo account">
    Sign up for an [Expo](https://expo.dev/signup) account, if you haven't already.
  </Requirement>
  <Requirement number={2} title="EAS CLI">
    The [EAS CLI](/build/setup/#install-the-latest-eas-cli) installed and logged in.
    ```sh
$ npm install -g eas-cli && eas login
```
  </Requirement>
  <Requirement number={3} title="Apple Developer account">
    A paid [Apple Developer](https://developer.apple.com/) account for creating [signing
    credentials](/app-signing/managed-credentials/#generating-app-signing-credentials) so the app
    could be installed on an iOS device.
  </Requirement>
</Prerequisites>
```sh
$ eas build --platform ios --profile development
```
iOS device builds can only be installed on iPhone devices and not on iOS Simulators.
Read more about [iOS device builds on EAS](/tutorial/eas/ios-development-build-for-devices/).
Step 3: 
### Install the app
You'll need to install the native app on your device, emulator, or simulator.
#### When building on EAS
If you create your development build on EAS, the CLI will prompt you to install the app after the build is finished. You can also install previous builds from the [expo.dev](https://expo.dev/) dashboard or using [Expo Orbit](https://expo.dev/orbit).
#### When building locally using EAS CLI
When building locally the output of the build will be an archive. You may drag and drop this on your Android Emulator/iOS Simulator to install it, or use [Expo Orbit](https://expo.dev/orbit) to install a build from your local machine.
Step 4: 
### Start the bundler
The development client built in **step 2** is the native side of your app (basically your own version of Expo Go). To continue developing, you'll also want to start the JavaScript bundler.
Depending on how you built the app, this may already be running, but if you close the process for any reason, there is no need to rebuild your development client. Simply restart the JavaScript bundler with:
```sh
$ npx expo start
```
This is the same command you would have used with Expo Go. It detects whether your project has `expo-dev-client` installed, in which case it will default to targeting your development build instead of Expo Go.
## Video walkthroughs


## Use a development build

Learn how to use development builds for a project.

Usually, creating a new native build from scratch takes long enough that you'll be tempted to switch tasks and lose your focus. However, with the development build installed on your device or an emulator/simulator, you won't have to wait for the native build process until you [change the underlying native code](#rebuild-a-development-build) that powers your app.
## Start the development server
To start developing, run the following command to start the development server:
```sh
$ npx expo start
```
To open the project inside your development client:
- Press <kbd>a</kbd> or <kbd>i</kbd> keys to open your project on an Android Emulator or an iOS Simulator.
- On a physical device, scan the QR code from your system's camera or a QR code reader to open the project on your device.
## The launcher screen
If you launch the development build from your device's Home screen, you will see your launcher screen, which looks similar to the following:
If a bundler is detected on your local network, or if you have signed in to an Expo account in both Expo CLI and your development build, you can connect to it directly from this screen. Otherwise, you can connect by scanning the QR code displayed by the Expo CLI.
## Rebuild a development build
If you add a library to your project that contains native code APIs, for example, [`expo-secure-store`](/versions/latest/sdk/securestore/), you will have to rebuild the development client. This is because the native code of the library is not included in the development client automatically when installing the library as a dependency on your project.
## Debug a development build
When you need to, you can access the menu by pressing <kbd>Cmd â</kbd> + <kbd>d</kbd> or <kbd>Ctrl</kbd> + <kbd>d</kbd> in Expo CLI or by shaking your phone or tablet. Here you'll be able to access all of the functions of your development build, any debugging functionality you need, or switch to a different version of your app.
See [Debugging](/debugging/runtime-issues/) guide for more information.


## Share a development build with your team

Learn how to install and share the development with your team or run it on multiple devices.

Android and iOS both offer ways to install a build of your application directly on devices. This gives you full control of putting specific builds on devices, allowing you to iterate quickly and have multiple builds of your application available for review at the same time. You can also share it with your team or run it on multiple test devices.
## Share the URL
When a development build is ready, a shareable URL is generated for your build with instructions on how to get it up and running. You can use this URL with a teammate or send it to your test device to install the build. The URL generated is unique to the build for your project.
> If you register any new iOS devices after creating a development build, you'll need to create a new development build to install it on those devices. For more information, see [internal distribution](/build/internal-distribution/).
### Use the EAS dashboard
You can also direct your teammate to the build page in the EAS dashboard. From there, they can download the build artifact directly on their device.
### Use EAS CLI
Your teammate can also download and install the development build using EAS CLI. They have to make sure that they are signed from the Expo account associated with the development build and then can run the following command:
```sh
$ eas build:run --profile development
```
If the profile name for the development build is different from `development`, use it instead with `--profile`.
### iOS-only instructions
> If you're running iOS 16 or above and haven't yet turned on Developer Mode, you'll need to [enable it](/guides/ios-developer-mode) before you can run your build. (This doesn't apply if you're using enterprise provisioning.)
You can use `eas build:resign` to codesign an existing **.ipa** for iOS to a new ad hoc provisioning profile. This helps reduce time when distributing with your team. For example, if you want to add a new test device to an existing build, you can use this command to update the provisioning profile to include the device without rebuilding the entire app from scratch. For more information, see [Re-signing new credentials](/app-signing/app-credentials/#re-signing-new-credentials).
## Next steps


## Tools, workflows and extensions

Learn more about different tools, workflows and extensions available when working with development builds.

Development builds allow you to iterate quickly. However, you can extend the capabilities of your development build to provide a better developer experience when working in teams or customize the build to suit your needs.
## Tools
### Tunnel URLs
Sometimes, restrictive network conditions make it difficult to connect to the development server. The `npx expo start` command exposes your development server on a publicly available URL that is accessible through firewalls from around the globe. This option is helpful if you are not able to connect to your development server with the default LAN option or if you want to get feedback on your implementation while you are developing.
To get a tunneled URL, pass the [`--tunnel` flag](/more/expo-cli/#tunneling) to `npx expo start` from the command line.
### Published updates
EAS CLI's `eas update` command bundles the current state of your JavaScript and asset files into an optimized "update". This update is stored on a hosting service by Expo. A development build of your app can load published updates without needing to check out a particular commit or leave a development machine running.
### Manually entering an update's URL
When a development build launches, it will expose UI to load a development server, or to "Enter URL manually". You can provide a URL manually that will launch a specific branch. The URL follows this pattern:
```text
https://u.expo.dev/[your-project-id]?channel-name=[channel-name]