# Expo Documentation Expo is an open-source React Native framework for apps that run natively on Android, iOS, and the web. Expo brings together the best of mobile and the web and enables many important features for building and scaling an app such as live updates, instantly sharing your app, and web support. The company behind Expo also offers Expo Application Services (EAS), which are deeply integrated cloud services for Expo and React Native apps. --- modificationDate: February 25, 2026 title: Introduction description: Get started creating apps with Expo. --- # Introduction Get started creating apps with Expo. Expo is a framework that makes developing Android and iOS apps easier. Our framework provides file-based routing, a standard library of native modules, and much more. Expo is open source with an active community on [GitHub](https://github.com/expo/expo) and [Discord](https://chat.expo.dev). We also make [Expo Application Services (EAS)](https://expo.dev/eas), a set of services that complement the Expo framework in each step of the development process. To get started visit: [Quick start docs](/get-started/create-a-project) — Create a project, set up your development environment, and start developing. --- --- modificationDate: February 25, 2026 title: Create a project description: Learn how to create a new Expo project. --- # Create a project Learn how to create a new Expo project. System requirements: - [Node.js (LTS)](https://nodejs.org/en/). - macOS, Windows (Powershell and [WSL 2](https://expo.fyi/wsl)), and Linux are supported. We recommend starting with the default project created by `create-expo-app`. The default project includes example code to help you get started. To create a new project, run the following command: ```sh npx create-expo-app@latest ``` > You can choose a different template by adding the [`--template` option](/more/create-expo#--template). ## Next step You have a project. Now it's time to set up your development environment so that you can start developing. --- --- modificationDate: February 25, 2026 title: Set up your environment description: Learn how to set up your development environment to start building with Expo. --- # Set up your environment Learn how to set up your development environment to start building with Expo. Let's set up a local development environment for running your project on Android and iOS. ## Where would you like to develop? We recommend using a real device to develop, since you'll get to see exactly what your users will see. ## How would you like to develop? Expo Go is a playground for students and learners to try Expo quickly. A development build is a build of your own app that includes Expo's developer tools. ## Android device with Expo Go ### Set up an Android device with Expo Go Scan the QR code to download the app from the Google Play Store, or visit the Expo Go page on the [Google Play Store](https://play.google.com/store/apps/details?id=host.exp.exponent&referrer=docs). Download link: [https://play.google.com/store/apps/details?id=host.exp.exponent&referrer=docs](https://play.google.com/store/apps/details?id=host.exp.exponent&referrer=docs) --- ## Android device with a development build (EAS) ### Set up an Android device with a development build #### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh npm install -g eas-cli ``` #### Create an Expo account and login To build your app, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh eas login ``` #### Configure your project Run the following command to create an EAS config in your project: ```sh eas build:configure ``` #### Create a build Run the following command to create a development build: ```sh eas build --platform android --profile development ``` #### Install the development build on your device After the build is complete, scan the QR code in your terminal or open the link on your device. Tap **Install** to download the build on your device, then tap **Open** to install it. --- ## Android device with a development build (local) ### Set up an Android device with a development build ### Install Watchman and JDK ##### macOS ##### Prerequisites Use a package manager such as [Homebrew](https://brew.sh/) to install the following dependency. ##### Install dependencies [Install Watchman](https://facebook.github.io/watchman/docs/install#macos) using a tool such as Homebrew: ```sh brew install watchman ``` Install OpenJDK distribution called Azul Zulu using Homebrew. This distribution offers JDKs for both Apple Silicon and Intel Macs. Run the following commands in a terminal: ```sh brew install --cask zulu@17 ``` After you install the JDK, add the `JAVA_HOME` environment variable in **~/.bash_profile** (or **~/.zshrc** if you use Zsh): ```bash export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` ##### Windows ##### Prerequisites Use a package manager such as [Chocolatey](https://chocolatey.org/) to install the following dependencies. ##### Install dependencies Install [Java SE Development Kit (JDK)](https://openjdk.org/): ```sh choco install -y microsoft-openjdk17 ``` ##### Linux ##### Install dependencies Follow [instructions from the Watchman documentation](https://facebook.github.io/watchman/docs/install#linux) to compile and install it from the source. Install [Java SE Development Kit (JDK)](https://openjdk.org/): You can download and install [OpenJDK@17](http://openjdk.java.net/) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. ### Set up Android Studio ##### macOS Download and install [Android Studio](https://developer.android.com/studio). Open the **Android Studio** app, you will see the **SDK Components setup** screen. Click **Next** to continue to install the Android SDK and Android SDK Platform. Click **Next** again to verify the settings and install. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. Copy or remember the path listed in the box that says **Android SDK Location**. Add the following lines to your **/.zprofile** or **~/.zshrc** (if you are using bash, then **~/.bash_profile** or **~/.bashrc**) config file: ```sh export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/platform-tools ``` Reload the path environment variables in your current shell: ```sh source $HOME/.zshrc source $HOME/.bashrc ``` Finally, make sure that you can run `adb` from your terminal. **Troubleshooting: Android Studio not recognizing JDK** If Android Studio doesn't recognize your homebrew installed JDK, you can create a Gradle configuration file to explicitly set the Java path: 1. Create a Gradle properties file in your home directory: ```sh touch ~/.gradle/gradle.properties ``` 2. Add the following line to the **gradle.properties** file, replacing the path with your actual Java installation path: ```bash gradle.properties java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` 3. If you have an existing `.gradle` folder in your project directory, delete it and reopen your project in Android Studio: ```sh rm -rf .gradle ``` This should resolve issues with Android Studio not detecting your JDK installation. ##### Windows Download [Android Studio](https://developer.android.com/studio). Open **Android Studio Setup**. Under **Select components to install**, select Android Studio and Android Virtual Device. Then, click **Next**. In the Android Studio Setup Wizard, under **Install Type**, select **Standard** and click **Next**. The Android Studio Setup Wizard will ask you to verify the settings, such as the version of Android SDK, platform-tools, and so on. Click **Next** after you have verified. In the next window, accept licenses for all available components. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. After the tools installation is complete, configure the `ANDROID_HOME` environment variable. Go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** and click **New** to create a new `ANDROID_HOME` user variable. The value of this variable will point to the path to your Android SDK: **How to find installed SDK location?** By default, the Android SDK is installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk ``` To find the location of the SDK in Android Studio manually, go to **Settings** > **Languages & Frameworks** > **Android SDK**. See the location next to **Android SDK Location**. To verify that the new environment variable is loaded, open **PowerShell**, and copy and paste the following command: ```sh Get-ChildItem -Path Env: ``` The command will output all user environment variables. In this list, see if `ANDROID_HOME` has been added. To add platform-tools to the Path, go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** > **Path** > **Edit** > **New** and add the path to the platform-tools to the list as shown below: **How to find installed platform-tools location** By default, the platform-tools are installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk\platform-tools ``` Finally, make sure that you can run `adb` from the PowerShell. For example, run the `adb --version` to see which version of the `adb` your system is running. ### Running your app on an Android device #### Install expo-dev-client Run the following command in your project's root directory: ```sh npx expo install expo-dev-client ``` #### Enable debugging over USB Most Android devices can only install and run apps downloaded from Google Play, by default. You will need to enable USB Debugging on your device to install your app during development. To enable USB debugging on your device, you will first need to enable the "Developer options" menu by going to **Settings** > **About phone** > **Software information** and then tapping the `Build number` row at the bottom seven times. You can then go back to **Settings** > **Developer options** to enable "USB debugging". #### Plug in your device via USB Plug in your Android device via USB to your computer. Check that your device is properly connecting to ADB, the Android Debug Bridge, by running `adb devices` in your terminal. You should see your device listed with `device` listed next to it. For example: ```sh adb devices List of devices attached 8AHX0T32K device ``` #### Run your app Run the following from your terminal: ```sh npx expo run:android ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. --- ## Android Emulator with Expo Go ### Set up an Android Emulator with Expo Go ### Set up Android Studio ##### macOS Download and install [Android Studio](https://developer.android.com/studio). Open the **Android Studio** app, you will see the **SDK Components setup** screen. Click **Next** to continue to install the Android SDK and Android SDK Platform. Click **Next** again to verify the settings and install. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. Copy or remember the path listed in the box that says **Android SDK Location**. Add the following lines to your **/.zprofile** or **~/.zshrc** (if you are using bash, then **~/.bash_profile** or **~/.bashrc**) config file: ```sh export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/platform-tools ``` Reload the path environment variables in your current shell: ```sh source $HOME/.zshrc source $HOME/.bashrc ``` Finally, make sure that you can run `adb` from your terminal. **Troubleshooting: Android Studio not recognizing JDK** If Android Studio doesn't recognize your homebrew installed JDK, you can create a Gradle configuration file to explicitly set the Java path: 1. Create a Gradle properties file in your home directory: ```sh touch ~/.gradle/gradle.properties ``` 2. Add the following line to the **gradle.properties** file, replacing the path with your actual Java installation path: ```bash gradle.properties java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` 3. If you have an existing `.gradle` folder in your project directory, delete it and reopen your project in Android Studio: ```sh rm -rf .gradle ``` This should resolve issues with Android Studio not detecting your JDK installation. ##### Windows Download [Android Studio](https://developer.android.com/studio). Open **Android Studio Setup**. Under **Select components to install**, select Android Studio and Android Virtual Device. Then, click **Next**. In the Android Studio Setup Wizard, under **Install Type**, select **Standard** and click **Next**. The Android Studio Setup Wizard will ask you to verify the settings, such as the version of Android SDK, platform-tools, and so on. Click **Next** after you have verified. In the next window, accept licenses for all available components. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. After the tools installation is complete, configure the `ANDROID_HOME` environment variable. Go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** and click **New** to create a new `ANDROID_HOME` user variable. The value of this variable will point to the path to your Android SDK: **How to find installed SDK location?** By default, the Android SDK is installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk ``` To find the location of the SDK in Android Studio manually, go to **Settings** > **Languages & Frameworks** > **Android SDK**. See the location next to **Android SDK Location**. To verify that the new environment variable is loaded, open **PowerShell**, and copy and paste the following command: ```sh Get-ChildItem -Path Env: ``` The command will output all user environment variables. In this list, see if `ANDROID_HOME` has been added. To add platform-tools to the Path, go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** > **Path** > **Edit** > **New** and add the path to the platform-tools to the list as shown below: **How to find installed platform-tools location** By default, the platform-tools are installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk\platform-tools ``` Finally, make sure that you can run `adb` from the PowerShell. For example, run the `adb --version` to see which version of the `adb` your system is running. ### Set up an emulator On the Android Studio main screen, click **More Actions**, then **Virtual Device Manager** in the dropdown. Click the **Create device** button. Under **Add device**, choose the type of hardware you'd like to emulate. We recommend testing against a variety of devices, but if you're unsure where to start, the newest device in the Pixel line could be a good choice. Select an OS version to load on the emulator (probably one of the system images), and download the image (if required). Change any other settings you'd like, and press **Finish** to create the emulator. You can now run this emulator anytime by pressing the Play button in the AVD Manager window. ### Install Expo Go When you start a development server with `npx expo start` on the [start developing](/get-started/start-developing) page, press a to open the Android Emulator. Expo CLI will install Expo Go automatically. --- ## Android Emulator with a development build (EAS) ### Set up an Android Emulator with a development build ### Set up Android Studio ##### macOS Download and install [Android Studio](https://developer.android.com/studio). Open the **Android Studio** app, you will see the **SDK Components setup** screen. Click **Next** to continue to install the Android SDK and Android SDK Platform. Click **Next** again to verify the settings and install. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. Copy or remember the path listed in the box that says **Android SDK Location**. Add the following lines to your **/.zprofile** or **~/.zshrc** (if you are using bash, then **~/.bash_profile** or **~/.bashrc**) config file: ```sh export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/platform-tools ``` Reload the path environment variables in your current shell: ```sh source $HOME/.zshrc source $HOME/.bashrc ``` Finally, make sure that you can run `adb` from your terminal. **Troubleshooting: Android Studio not recognizing JDK** If Android Studio doesn't recognize your homebrew installed JDK, you can create a Gradle configuration file to explicitly set the Java path: 1. Create a Gradle properties file in your home directory: ```sh touch ~/.gradle/gradle.properties ``` 2. Add the following line to the **gradle.properties** file, replacing the path with your actual Java installation path: ```bash gradle.properties java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` 3. If you have an existing `.gradle` folder in your project directory, delete it and reopen your project in Android Studio: ```sh rm -rf .gradle ``` This should resolve issues with Android Studio not detecting your JDK installation. ##### Windows Download [Android Studio](https://developer.android.com/studio). Open **Android Studio Setup**. Under **Select components to install**, select Android Studio and Android Virtual Device. Then, click **Next**. In the Android Studio Setup Wizard, under **Install Type**, select **Standard** and click **Next**. The Android Studio Setup Wizard will ask you to verify the settings, such as the version of Android SDK, platform-tools, and so on. Click **Next** after you have verified. In the next window, accept licenses for all available components. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. After the tools installation is complete, configure the `ANDROID_HOME` environment variable. Go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** and click **New** to create a new `ANDROID_HOME` user variable. The value of this variable will point to the path to your Android SDK: **How to find installed SDK location?** By default, the Android SDK is installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk ``` To find the location of the SDK in Android Studio manually, go to **Settings** > **Languages & Frameworks** > **Android SDK**. See the location next to **Android SDK Location**. To verify that the new environment variable is loaded, open **PowerShell**, and copy and paste the following command: ```sh Get-ChildItem -Path Env: ``` The command will output all user environment variables. In this list, see if `ANDROID_HOME` has been added. To add platform-tools to the Path, go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** > **Path** > **Edit** > **New** and add the path to the platform-tools to the list as shown below: **How to find installed platform-tools location** By default, the platform-tools are installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk\platform-tools ``` Finally, make sure that you can run `adb` from the PowerShell. For example, run the `adb --version` to see which version of the `adb` your system is running. ### Set up an emulator On the Android Studio main screen, click **More Actions**, then **Virtual Device Manager** in the dropdown. Click the **Create device** button. Under **Add device**, choose the type of hardware you'd like to emulate. We recommend testing against a variety of devices, but if you're unsure where to start, the newest device in the Pixel line could be a good choice. Select an OS version to load on the emulator (probably one of the system images), and download the image (if required). Change any other settings you'd like, and press **Finish** to create the emulator. You can now run this emulator anytime by pressing the Play button in the AVD Manager window. ### Create a development build #### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh npm install -g eas-cli ``` #### Create an Expo account and login To build your app, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh eas login ``` #### Configure your project Run the following command to create an EAS config in your project: ```sh eas build:configure ``` #### Create a build Run the following command to create a development build: ```sh eas build --platform android --profile development ``` #### Install the development build on your emulator After the build is complete, the CLI will prompt you to automatically download and install it on the Android Emulator. When prompted, press Y to directly install it on the emulator. If you miss this prompt, you can download the build from the link provided in the terminal and drag and drop it onto the Android Emulator to install it. --- ## Android Emulator with a development build (local) ### Set up an Android Emulator with a development build ### Install Watchman and JDK ##### macOS ##### Prerequisites Use a package manager such as [Homebrew](https://brew.sh/) to install the following dependency. ##### Install dependencies [Install Watchman](https://facebook.github.io/watchman/docs/install#macos) using a tool such as Homebrew: ```sh brew install watchman ``` Install OpenJDK distribution called Azul Zulu using Homebrew. This distribution offers JDKs for both Apple Silicon and Intel Macs. Run the following commands in a terminal: ```sh brew install --cask zulu@17 ``` After you install the JDK, add the `JAVA_HOME` environment variable in **~/.bash_profile** (or **~/.zshrc** if you use Zsh): ```bash export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` ##### Windows ##### Prerequisites Use a package manager such as [Chocolatey](https://chocolatey.org/) to install the following dependencies. ##### Install dependencies Install [Java SE Development Kit (JDK)](https://openjdk.org/): ```sh choco install -y microsoft-openjdk17 ``` ##### Linux ##### Install dependencies Follow [instructions from the Watchman documentation](https://facebook.github.io/watchman/docs/install#linux) to compile and install it from the source. Install [Java SE Development Kit (JDK)](https://openjdk.org/): You can download and install [OpenJDK@17](http://openjdk.java.net/) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. ### Set up Android Studio ##### macOS Download and install [Android Studio](https://developer.android.com/studio). Open the **Android Studio** app, you will see the **SDK Components setup** screen. Click **Next** to continue to install the Android SDK and Android SDK Platform. Click **Next** again to verify the settings and install. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. Copy or remember the path listed in the box that says **Android SDK Location**. Add the following lines to your **/.zprofile** or **~/.zshrc** (if you are using bash, then **~/.bash_profile** or **~/.bashrc**) config file: ```sh export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/platform-tools ``` Reload the path environment variables in your current shell: ```sh source $HOME/.zshrc source $HOME/.bashrc ``` Finally, make sure that you can run `adb` from your terminal. **Troubleshooting: Android Studio not recognizing JDK** If Android Studio doesn't recognize your homebrew installed JDK, you can create a Gradle configuration file to explicitly set the Java path: 1. Create a Gradle properties file in your home directory: ```sh touch ~/.gradle/gradle.properties ``` 2. Add the following line to the **gradle.properties** file, replacing the path with your actual Java installation path: ```bash gradle.properties java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` 3. If you have an existing `.gradle` folder in your project directory, delete it and reopen your project in Android Studio: ```sh rm -rf .gradle ``` This should resolve issues with Android Studio not detecting your JDK installation. ##### Windows Download [Android Studio](https://developer.android.com/studio). Open **Android Studio Setup**. Under **Select components to install**, select Android Studio and Android Virtual Device. Then, click **Next**. In the Android Studio Setup Wizard, under **Install Type**, select **Standard** and click **Next**. The Android Studio Setup Wizard will ask you to verify the settings, such as the version of Android SDK, platform-tools, and so on. Click **Next** after you have verified. In the next window, accept licenses for all available components. By default, Android Studio will install the latest version of the Android SDK. However, Android 15 (`VanillaIceCream`) SDK is required to compile a React Native app. Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, and under **Android 15 (`VanillaIceCream`)**, select **Android SDK Platform 35** and **Sources for Android 35**. Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. After the tools installation is complete, configure the `ANDROID_HOME` environment variable. Go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** and click **New** to create a new `ANDROID_HOME` user variable. The value of this variable will point to the path to your Android SDK: **How to find installed SDK location?** By default, the Android SDK is installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk ``` To find the location of the SDK in Android Studio manually, go to **Settings** > **Languages & Frameworks** > **Android SDK**. See the location next to **Android SDK Location**. To verify that the new environment variable is loaded, open **PowerShell**, and copy and paste the following command: ```sh Get-ChildItem -Path Env: ``` The command will output all user environment variables. In this list, see if `ANDROID_HOME` has been added. To add platform-tools to the Path, go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** > **Path** > **Edit** > **New** and add the path to the platform-tools to the list as shown below: **How to find installed platform-tools location** By default, the platform-tools are installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk\platform-tools ``` Finally, make sure that you can run `adb` from the PowerShell. For example, run the `adb --version` to see which version of the `adb` your system is running. ### Set up an emulator On the Android Studio main screen, click **More Actions**, then **Virtual Device Manager** in the dropdown. Click the **Create device** button. Under **Add device**, choose the type of hardware you'd like to emulate. We recommend testing against a variety of devices, but if you're unsure where to start, the newest device in the Pixel line could be a good choice. Select an OS version to load on the emulator (probably one of the system images), and download the image (if required). Change any other settings you'd like, and press **Finish** to create the emulator. You can now run this emulator anytime by pressing the Play button in the AVD Manager window. ### Running your app on an Android Emulator #### Install expo-dev-client Run the following command in your project's root directory: ```sh npx expo install expo-dev-client ``` Run the following from your terminal: ```sh npx expo run:android ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. --- ## iOS device with Expo Go ### Set up an iOS device with Expo Go Scan the QR code to download the app from the App Store, or visit the Expo Go page on the [App Store](https://itunes.apple.com/app/apple-store/id982107779). Download link: [https://itunes.apple.com/app/apple-store/id982107779](https://itunes.apple.com/app/apple-store/id982107779) --- ## iOS device with a development build (EAS) ### Set up an iOS device with a development build #### Enroll in the Apple Developer Program To install a development build on your iOS device, you will need an active subscription to the Apple Developer Program. Sign up for the [Apple Developer Program here](https://developer.apple.com/programs/). #### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh npm install -g eas-cli ``` #### Create an Expo account and login Next, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh eas login ``` #### Configure your project Run the following command to create an EAS config in your project: ```sh eas build:configure ``` #### Create an ad hoc provisioning profile To install a development build on your iOS device, you will need to create an ad hoc provisioning profile. Create one by running the following command in your terminal: ```sh eas device:create ``` #### Create a development build Run the following command to create a development build: ```sh eas build --platform ios --profile development ``` #### Install the development build on your device After the build is complete, scan the QR code in your terminal and tap **Open with iTunes** when it appears inside the Camera app. Alternatively, open the link displayed in the terminal on your device. After confirming the installation, the app will appear in your device's app library. #### Turn on developer mode 1. Open **Settings** > **Privacy & Security**, scroll down to the **Developer Mode** list item and navigate into it. 2. Tap the switch to enable **Developer Mode**. After you do so, Settings presents an alert to warn you that Developer Mode reduces your device's security. To continue enabling **Developer Mode**, tap the alert's **Restart** button. 3. After the device restarts and you unlock it, the device shows an alert confirming that you want to enable Developer Mode. Tap **Turn On**, and enter your device passcode when prompted. > Alternatively, if you have Xcode installed on your Mac, you can use it to [enable iOS developer mode](/guides/ios-developer-mode/#connect-an-ios-device-with-a-mac). --- ## iOS device with a development build (local) ### Set up an iOS device with a development build ### Set up Xcode and Watchman #### Install Xcode Open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and click **Install** (or **Update** if you have it already). #### Install Xcode Command Line Tools Open Xcode, choose **Settings...** from the Xcode menu (or press cmd ⌘ + ,). Go to the **Locations** and install the tools by selecting the most recent version in the **Command Line Tools** dropdown. #### Install an iOS Simulator in Xcode To install an iOS Simulator, open **Xcode > Settings... > Components**, and under **Platform Support > iOS ...**, click **Get**. #### Install Watchman [Watchman](https://facebook.github.io/watchman/docs/install#macos) is a tool for watching changes in the filesystem. Installing it will result in better performance. You can install it with: ```sh brew update brew install watchman ``` ### Configure your project #### Install expo-dev-client Run the following command in your project's root directory: ```sh npx expo install expo-dev-client ``` #### Plug in your device via USB and enable developer mode 1. Connect your iOS device to your Mac using a USB cable. Unlock the device and tap **Trust** if prompted. 2. Open Xcode. From the menu bar, select **Window** > **Devices and Simulators**. You will see a warning in Xcode to enable developer mode. 3. On your iOS device, open **Settings** > **Privacy & Security**, scroll down to the **Developer Mode** list item and navigate into it. 4. Tap the switch to enable **Developer Mode**. After you do so, Settings presents an alert to warn you that Developer Mode reduces your device's security. To continue enabling **Developer Mode**, tap the alert's **Restart** button. 5. After the device restarts and you unlock it, the device shows an alert confirming that you want to enable Developer Mode. Tap **Turn On**, and enter your device passcode when prompted. #### Run the project on your device 1. Add the `ios.bundleIdentifier` in the **app.json** file in the root directory to a unique value so that Xcode generates the provisioning profile for the app signing step. 2. Run the following command in your project's root directory and select your plugged in device from the list: ```sh npx expo run:ios --device ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. --- ## iOS Simulator with Expo Go ### Set up an iOS Simulator with Expo Go ### Set up Xcode #### Install Xcode Open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and click **Install** (or **Update** if you have it already). #### Install Xcode Command Line Tools Open Xcode, choose **Settings...** from the Xcode menu (or press cmd ⌘ + ,). Go to the **Locations** and install the tools by selecting the most recent version in the **Command Line Tools** dropdown. #### Install an iOS Simulator in Xcode To install an iOS Simulator, open **Xcode > Settings... > Components**, and under **Platform Support > iOS ...**, click **Get**. #### Install Watchman [Watchman](https://facebook.github.io/watchman/docs/install#macos) is a tool for watching changes in the filesystem. Installing it will result in better performance. You can install it with: ```sh brew update brew install watchman ``` ### Install Expo Go When you start a development server with `npx expo start` on the [start developing](/get-started/start-developing) page, press i to open the iOS Simulator. Expo CLI will install Expo Go automatically. --- ## iOS Simulator with a development build (EAS) ### Set up an iOS Simulator with a development build ### Set up Xcode #### Install Xcode Open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and click **Install** (or **Update** if you have it already). #### Install Xcode Command Line Tools Open Xcode, choose **Settings...** from the Xcode menu (or press cmd ⌘ + ,). Go to the **Locations** and install the tools by selecting the most recent version in the **Command Line Tools** dropdown. #### Install an iOS Simulator in Xcode To install an iOS Simulator, open **Xcode > Settings... > Components**, and under **Platform Support > iOS ...**, click **Get**. #### Install Watchman [Watchman](https://facebook.github.io/watchman/docs/install#macos) is a tool for watching changes in the filesystem. Installing it will result in better performance. You can install it with: ```sh brew update brew install watchman ``` ### Create a development build #### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh npm install -g eas-cli ``` #### Create an Expo account and login Next, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh eas login ``` #### Configure your project Run the following command to create an EAS config in your project: ```sh eas build:configure ``` #### Adjust your build profile To create a simulator-compatible development build, you'll need to update your build profile in **eas.json** to set the `ios.simulator` property to `true`: ```json eas.json { "build": { "development": { "developmentClient": true, "distribution": "internal", /* @info */ "ios": { "simulator": true } /* @end */ } } } ``` #### Create a development build Run the following command to create a development build: ```sh eas build --platform ios --profile development ``` #### Install the development build on your simulator After the build is complete, the CLI will prompt you to automatically download and install it on the iOS Simulator. When prompted, press Y to directly install it on the simulator. If you miss this prompt, you can download the build from the link provided in the terminal and drag and drop it onto the iOS Simulator to install it. --- ## iOS Simulator with a development build (local) ### Set up an iOS Simulator with a development build ### Set up Xcode and Watchman #### Install Xcode Open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and click **Install** (or **Update** if you have it already). #### Install Xcode Command Line Tools Open Xcode, choose **Settings...** from the Xcode menu (or press cmd ⌘ + ,). Go to the **Locations** and install the tools by selecting the most recent version in the **Command Line Tools** dropdown. #### Install an iOS Simulator in Xcode To install an iOS Simulator, open **Xcode > Settings... > Components**, and under **Platform Support > iOS ...**, click **Get**. #### Install Watchman [Watchman](https://facebook.github.io/watchman/docs/install#macos) is a tool for watching changes in the filesystem. Installing it will result in better performance. You can install it with: ```sh brew update brew install watchman ``` ### Running your app on an iOS Simulator #### Install expo-dev-client Run the following command in your project's root directory: ```sh npx expo install expo-dev-client ``` Run the following from your terminal: ```sh npx expo run:ios ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. ## Next step You have a project and a development environment. Now it's time to start developing. --- --- modificationDate: February 25, 2026 title: Start developing description: Make your first change to an Expo project and see it live on your device. --- # Start developing Make your first change to an Expo project and see it live on your device. ## Start a development server To start the development server, run the following command: ```sh npx expo start ``` ## Open the app on your device After running the command above, you will see a QR code in your terminal. Scan this QR code to open the app on your device. If you're using an Android Emulator or iOS Simulator, you can press a or i respectively to open the app. Having problems? Make sure you are on the same Wi-Fi network on your computer and your device. If it still doesn't work, it may be due to the router configuration — this is common for public networks. You can work around this by choosing the **Tunnel** connection type when starting the development server, then scanning the QR code again. ```sh npx expo start --tunnel ``` > Using the **Tunnel** connection type will make the app reloads considerably slower than on **LAN** or **Local**, so it's best to avoid tunnel when possible. You may want to install and use an emulator or simulator to speed up development if **Tunnel** is required to access your machine from another device on your network. ## Make your first change Open the **app/(tabs)/index.tsx** file in your code editor and make a change. ```diff } > - Welcome! + Hello World! ``` Changes not showing up on your device? Expo Go is configured by default to automatically reload the app whenever a file is changed, but let's make sure to go over the steps to enable it in case somehow things aren't working. - Make sure you have the [development mode enabled in Expo CLI](/workflow/development-mode#development-mode). - Close the Expo app and reopen it. - Once the app is open again, shake your device to reveal the developer menu. If you are using an emulator, press Ctrl + M for Android or Cmd ⌘ + D for iOS. - If you see **Enable Fast Refresh**, press it. If you see **Disable Fast Refresh**, dismiss the developer menu. Now try making another change. ## File structure Below, you can get familiar with the default project's file structure: Files ### app Contains the app's navigation, which is file-based. The file structure of the **app** directory determines the app's navigation. The app has two routes defined by two files: **app/(tabs)/index.tsx** and **app/(tabs)/explore.tsx**. The layout file in **app/(tabs)/_layout.tsx** sets up the tab navigator. ## Features The default project template has the following features: Default project ### File-based routing The app has two screens: **app/(tabs)/index.tsx** and **app/(tabs)/explore.tsx**. The layout file in **app/(tabs)/_layout.tsx** sets up the tab navigator. --- --- modificationDate: February 25, 2026 title: Next steps description: Develop, review, and submit your project. --- # Next steps Develop, review, and submit your project. Here are next steps to continue building your app: ### Reset your project You can remove the boilerplate code and start fresh with a new project. Run the following command to reset your project: ```sh npm run reset-project ``` This command will move the existing files in **app** to **app-example**, then create a new **app** directory with a new **index.tsx** file. ### Develop, review, and deploy Learn how to develop by reading the docs in the Develop section. You'll learn how to create [UI elements](/develop/user-interface/splash-screen-and-app-icon), add [unit tests](/develop/unit-testing), include [native modules](/config-plugins/introduction), and more. Once you've developed your app, you can share it with your teammates for [review](/review/overview). Finally, you can [build](/deploy/build-project) and [submit](/deploy/submit-to-app-stores) your project to the app stores. ### Step-by-step guide For a guided, step-by-step walkthrough of building an app with Expo from start to finish, check out the [tutorial](/tutorial/introduction). --- --- modificationDate: February 25, 2026 title: Tools for development description: An overview of Expo tools and websites that will help you during various aspects of your project-building journey. --- # Tools for development An overview of Expo tools and websites that will help you during various aspects of your project-building journey. When you create a new project with Expo, learning about the following essential tools and websites can help you during your app development journey. This page provides an overview of a list of recommended tools. ## Expo CLI Expo CLI is a development tool and is installed automatically with the `expo` package when you create a new project. You can use it by leveraging `npx` (a Node.js package runner). It is designed to help you move faster during the app development phase. For example, your first interaction with Expo CLI is starting the development server by running the command: `npx expo start`. The following is a list of common commands that you will use with Expo CLI while developing your app: | Command | Description | | --- | --- | | `npx expo start` | Starts the development server (whether you are using a development build or Expo Go). | | `npx expo prebuild` | Generates native Android and iOS directories using [Prebuild](/workflow/prebuild). | | `npx expo run:android` | Compiles native Android app locally. | | `npx expo run:ios` | Compiles native iOS app locally. | | `npx expo install package-name` | Used to install a new library or validate and update specific libraries in your project by adding `--fix` option to this command. | | `npx expo lint` | [Setup and configures](/guides/using-eslint) ESLint. If ESLint is already configured, this command will [lint your project files](/guides/using-eslint#usage). | In a nutshell, Expo CLI allows you to develop, compile, start your app, and more. See [Expo CLI reference](/more/expo-cli) for more available options and actions you can perform with the CLI. ## EAS CLI EAS CLI is used to log in to your Expo account and compile your app using different EAS services such as Build, Update, or Submit. You can also use this tool to: - Publish your app to the app stores - Create a development, preview, or production build of your app - Create over-the-air (OTA) updates - Manage your app credentials - Create an ad hoc provisioning profile for an iOS device To use EAS CLI, you need to install it globally on your local machine by running the command: ```sh npm install -g eas-cli ``` You can use `eas --help` in your terminal window to learn more about the available commands. For a complete reference, see [`eas-cli` npm page](https://www.npmjs.com/package/eas-cli). ## Expo Doctor Expo Doctor is a command line tool used to diagnose issues in your Expo project. To use it, run the following command in your project's root directory: ```sh npx expo-doctor ``` This command performs checks and analyzes your project's codebase for common issues in [app config](/workflow/configuration) and **package.json** files, dependency compatibility, configuration files, and the overall health of the project. Once the check is complete, Expo Doctor outputs the results. If Expo Doctor finds an issue, it provides a description of the problem along with advice on how to fix it or where to find help. By default, Expo Doctor validates your project's packages against the [React Native directory](https://reactnative.directory/) and checks if app config properties are properly synced when native directories exist. You can configure these checks in your project's **package.json** file. See [`reactNativeDirectoryCheck`](/versions/latest/config/package-json#reactnativedirectorycheck) and [`appConfigFieldsNotSyncedCheck`](/versions/latest/config/package-json#appconfigfieldsnotsynced) for more details. You can also use `npx expo-doctor --help` to display usage information. ## Orbit Orbit is a macOS and Windows app that enables: - Install and launch builds from EAS on physical devices and emulators. - Install and launch updates from EAS on Android Emulators or iOS Simulators. - Launch snack projects on Android Emulators or iOS Simulators. - Use local files to install and launch apps. Orbit supports any Android **.apk**, iOS Simulator compatible **.app**, or ad hoc signed apps. - See a list of pinned projects from your EAS dashboard. ### Installation You can download Orbit with Homebrew for macOS, or directly from the [GitHub releases](https://github.com/expo/orbit/releases). ```sh brew install expo-orbit ``` If you want Orbit to start when you log in automatically, click on the Orbit icon in the menu bar, then **Settings** and select the **Launch on Login** option. > Orbit relies on the Android SDK on both macOS and Windows and `xcrun` for device management only on macOS, which requires setting up both [Android Studio](/workflow/android-studio-emulator) and [Xcode](/workflow/ios-simulator). ## Expo Tools for VS Code Expo Tools is a VS Code extension to improve your development experience when working with app config files. It provides features such as autocomplete and intellisense for files such as app config, EAS config, store config and Expo Module config files. [Install Expo Tools VS Code extension](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools) — Use this link to install the extension or search Expo Tools directly in your VS Code editor. You can also use it to debug your app using VS Code's built-in debugger to set breakpoints, inspect variables, execute code through the debug console, and more. See [Debugging with VS Code](/debugging/tools#debugging-with-vs-code) for how to use this extension for debugging. ## Test prototypes with Snack and Expo Go ### Snack Snack is an in-browser development environment that works similarly to Expo Go. It's a great way to share code snippets and experiment with React Native without downloading any tools on your computer. To use it, go to [snack.expo.dev](https://snack.expo.dev/), edit the `` component in **App.js**, choose a platform (Android, iOS, or web) in the right panel and see the changes live. ### Expo Go [Expo Go](https://expo.dev/go) is a free, open-source playground for students and learners to try out React Native. It works with Android and iOS. For more information on how to use it: - Click [this link](/get-started/set-up-your-environment?mode=expo-go) to go to Set up your environment guide - Select a platform to develop under **Where would you like to develop?** - Select Expo Go under **How would you like to develop?** - Follow the instructions described in that guide > **Note:** Expo Go is limited and not useful for building production-grade projects. Use [development builds](/get-started/set-up-your-environment?mode=development-build) instead. What if I open a project with an unsupported SDK version? When running a project that was created for an unsupported SDK version in Expo Go, you'll see the following error: ```sh "Project is incompatible with this version of Expo Go" ``` To fix this, upgrading your project to a [supported SDK version](/versions/latest#each-expo-sdk-version-depends-on-a-react-native-version) is recommended. If you want to learn how to do it, see [Upgrade the project to a new SDK Version](/develop/tools#how-do-i-upgrade-my-project-from). How do I upgrade my project from an unsupported SDK version? See [Upgrading Expo SDK guide](/workflow/upgrading-expo-sdk-walkthrough) for instructions for upgrading to a specific SDK version. ## React Native directory Any library that is compatible with React Native works in an Expo project when you use a development build to create your project. [reactnative.directory](https://reactnative.directory/) is a searchable database for React Native libraries. If a library you are looking for is not included in Expo SDK, use the directory to find a compatible library for your project. [Use libraries](/workflow/using-libraries) — See this guide to learn more about the difference between React Native core libraries, Expo SDK libraries, and third-party libraries. It also explains how to determine third-party library compatibility. --- --- modificationDate: February 25, 2026 title: Navigation in Expo and React Native apps description: Learn about the recommended approach for integrating navigation in an Expo and React Native project. --- # Navigation in Expo and React Native apps Learn about the recommended approach for integrating navigation in an Expo and React Native project. The core React Native library does not include a built-in navigation solution, so you can choose a navigation library that best fits your needs. For Expo and React Native apps, it is generally a choice between [React Navigation](https://reactnavigation.org/) or [Expo Router](/router/introduction). ## Why React Native apps needs a navigation library React Native core includes basic UI components, touch handling, device APIs and networking, but excludes, among other things, storage, camera, maps, most device sensors, and **navigation**! These are intended to be covered by community libraries. ## React Navigation React Navigation is a component-based navigation library widely used across the React Native ecosystem. It lets you compose stack, tab, and drawer navigators entirely in code so you can implement complex flows, custom transitions, and app-specific UX patterns. The library offers platform-specific look-and-feel with smooth animations and gestures, unified mobile and web routing, automatic deep links, type routes with static configuration, and is highly customizable. [React Navigation: Getting started](https://reactnavigation.org/docs/getting-started) — Learn how to get started with React Navigation. ## Expo Router (recommended for Expo projects) Expo Router is a file-based routing library for Expo and React Native projects and is a built on top of React Navigation. By following the **app** directory convention, it turns files into routes and is integrated with Expo for [Expo CLI](/more/expo-cli) and bundling without additional setup. The library also adds features such as typed routes, dynamic routes, lazy bundling in development, static rendering for the web, and automatic deep linking. New Expo projects created with `npx create-expo-app@latest` include Expo Router by default so you can ship cross-platform navigation quickly while still being able to reach for React Navigation APIs when needed. [Introduction to Expo Router](/router/introduction) — Expo Router is an open-source routing library for Universal React Native applications built with Expo. [Installation](/router/installation) — Learn how to quickly get started by creating a new project with Expo Router or adding the library to an existing project. [Core concepts](/router/basics/core-concepts) — Learn about the core concepts of file-based routing in Expo. --- --- modificationDate: February 25, 2026 title: Splash screen and app icon description: Learn how to add a splash screen and app icon to your Expo project. --- # Splash screen and app icon Learn how to add a splash screen and app icon to your Expo project. A splash screen and an app icon are fundamental elements of a mobile app. They play an important role in the user experience and branding of the app. This guide provides steps on how to create and add them to your app. [Create an App Icon and Splash Screen](https://www.youtube.com/watch?v=3Bsw8a1BJoQ) — See a detailed walkthrough on how to create an app icon and splash screen for an Expo project. ## Splash screen A splash screen, also known as a launch screen, is the first screen a user sees when they open your app. It stays visible while the app is loading. You can also control the behavior of when a splash screen disappears by using the native [SplashScreen API](/versions/latest/sdk/splash-screen). The [`expo-splash-screen`](/versions/latest/sdk/splash-screen) has a built-in [config plugin](/config-plugins/introduction) that lets you configure properties such as the splash icon and background color. > **Do not use Expo Go or a development build to test your splash screen**. Expo Go renders your app icon while the splash screen is visible, which can interfere with testing. Development builds include `expo-dev-client`, which has its own splash screen and may cause conflicts. **Instead, use a [preview build](/build/eas-json#preview-builds) or a [production build](/build/eas-json#production-builds)**. ### Create a splash screen icon To create a splash screen icon, you can use this [Figma template](https://www.figma.com/community/file/1466490409418563617). It provides a bare minimum design for an icon and splash images for Android and iOS. **Recommended:** - Use a 1024x1024 image. - Use a **.png** file. - Use a transparent background. ### Export the splash icon as a .png After creating a splash screen icon, export it as a **.png** and save it in the **assets/images** directory. By default, Expo uses **splash-icon.png** as the file name. If you decide to change the name of your splash screen file, make sure to use that in the next step. > **Note:** **Currently, only .png images are supported** to use as a splash screen icon in an Expo project. If you use another image format, making a production build of your app will fail. ### Configure the splash screen icon Open the app config file, and under plugins, set the following properties: ```json { "expo": { "plugins": [ [ "expo-splash-screen", { "backgroundColor": "#232323", "image": "./assets/images/splash-icon.png", "dark": { "image": "./assets/images/splash-icon-dark.png", "backgroundColor": "#000000" }, "imageWidth": 200 } ] ] } } ``` To test your new splash screen, build your app for [internal distribution](/tutorial/eas/internal-distribution-builds) or for production, see guides on [Android](/tutorial/eas/android-production-build) and [iOS](/tutorial/eas/ios-production-build). [Configurable splash screen properties](/versions/latest/sdk/splash-screen#configurable-properties) — Learn about the configurable properties of the SplashScreen API. Configuring `expo-splash-screen` properties separately for Android and iOS [`expo-splash-screen`](/versions/latest/sdk/splash-screen) also supports `android` and `ios` properties for configuring the splash screen for a specific platform. See the following example: ```json { "expo": { "plugins": [ [ "expo-splash-screen", { "ios": { "backgroundColor": "#ffffff", "image": "./assets/images/splash-icon.png", "resizeMode": "cover" }, "android": { "backgroundColor": "#0c7cff", "image": "./assets/images/splash-android-icon.png", "imageWidth": 150 } } ] ] } } ``` Not using prebuild? If your app does not use [Expo Prebuild](/workflow/prebuild) (formerly the _managed workflow_) to generate the native **android** and **ios** directories, then changes in the app config will have no effect. For more information, see [how you can customize the configuration manually](https://github.com/expo/expo/tree/main/packages/expo-splash-screen#-installation-in-bare-react-native-projects). Troubleshooting: New splash screen not appearing on iOS For SDK versions below 52, in iOS development builds, launch screens can sometimes remain cached between builds, making it harder to test new images. Apple recommends clearing the _derived data_ directory before rebuilding, this can be done with Expo CLI by running: ```sh npx expo run:ios --no-build-cache ``` See [Apple's guide on testing launch screens](https://developer.apple.com/documentation/technotes/tn3118-debugging-your-apps-launch-screen) for more information. ## App icon An app's icon is what your app users see on their device's home screen and app stores. Android and iOS have different and strict requirements. ### Create an app icon To create an app icon, you can use this [Figma template](https://www.figma.com/community/file/1466490409418563617). It provides a bare minimum design for an icon and splash images for Android and iOS. ### Export the icon image as a .png After creating an app icon, export it as **.png** and save it in the **assets/images** directory. By default, Expo uses **icon.png** as the file name. If you decide to use a different file name, make sure to use that in the next step. ### Add the icon in app config Open the app config and add the local path as the value of [`icon`](/versions/latest/config/app#icon) property to point it to your new app icon: ```json { "icon": "./assets/images/icon.png" } ``` Custom configuration tips for Android and iOS #### Android Further customization of the Android icon is possible using the [`android.adaptiveIcon`](/versions/latest/config/app#adaptiveicon) property, which will override both of the previously mentioned settings. The Android Adaptive Icon is formed from two separate layers — a foreground image and a background color or image. This allows the OS to mask the icon into different shapes and also supports visual effects. For Android 13 and later, the OS supports a themed app icon that uses a wallpaper and theme to determine the color set by the device's theme. The design you provide should follow the [Android Adaptive Icon Guidelines](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive) for launcher icons. You should also: - Use **.png** files. - Use the `android.adaptiveIcon.foregroundImage` property to specify the path to your foreground image. - Use the `android.adaptiveIcon.monochromeImage` property to specify the path to your monochrome image. - The default background color is white; to specify a different background color, use the `android.adaptiveIcon.backgroundColor` property. You can instead specify a background image using the `android.adaptiveIcon.backgroundImage` property. Make sure that it has the same dimensions as your foreground image. You may also want to provide a separate icon for older Android devices that do not support Adaptive Icons. You can do so with the `android.icon` property. This single icon would be a combination of your foreground and background layers. > See [Apple best practices](https://developer.apple.com/design/human-interface-guidelines/app-icons/#Best-practices) to ensure your icon looks professional, such as testing your icon on different wallpapers and avoiding text beside your product's wordmark. Provide an icon that's at least 512x512 pixels. #### iOS [Icon Composer](https://www.youtube.com/watch?v=RZ_QMym3adw) — Learn how to use the new Icon Composer to create app icons for an Expo project. For iOS, your app's icon should follow the [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/app-icons/). You can use the [Icon Composer](https://developer.apple.com/icon-composer/) app to create your app icon. This will output a **.icon** directory that you can add to your project's **assets** directory. You can then provide the path to this directory in your app config. Adding support for dark mode is handled in Icon Composer, so you do not need to provide variants when using this approach. > **Note:** Providing an Icon Composer **.icon** directory via `ios.icon` is supported **in SDK 54** and later. ```json { "expo": { "ios": { "icon": "./assets/app.icon" } } } ``` Alternatively, the previous approach of providing an image is still supported. You should: - Use a **.png** file. - 1024x1024 is a good size. If you have an Expo project created using `npx create-expo-app`, [EAS Build](/build/setup) will generate the other sizes for you. In case of a bare React Native project, generate the icons on your own. The largest size EAS Build generates is 1024x1024. - The icon must be exactly square. For example, a 1023x1024 icon is not valid. - Make sure the icon fills the whole square, with no rounded corners or other transparent pixels. The operating system will mask your icon when appropriate. - Use `ios.icon` to specify different icons for various system appearances (for example, dark and tinted) can be provided. If specified, this overrides the top-level icon key in the app config file. See the example below: ```json { "expo": { "ios": { "icon": { "dark": "./assets/images/ios-dark.png", "light": "./assets/images/ios-light.png", "tinted": "./assets/images/ios-tinted.png" } } } } ``` --- --- modificationDate: February 25, 2026 title: Safe areas description: Learn how to add safe areas for screen components inside your Expo project. --- # Safe areas Learn how to add safe areas for screen components inside your Expo project. Creating a safe area ensures your app screen's content is positioned correctly. This means it doesn't get overlapped by notches, status bars, home indicators, and other interface elements that are part of the device's physical hardware or are controlled by the operating system. When the content gets overlapped, it gets concealed by these interface elements. Here's an example of an app screen's content getting concealed by the status bar on Android. On iOS, the same content is concealed by rounded corners, notch, and the status bar. ## Use `react-native-safe-area-context` library [`react-native-safe-area-context`](https://github.com/AppAndFlow/react-native-safe-area-context) provides a flexible API for handling Android and iOS device's safe area insets. It also provides a `SafeAreaView` component that you can use instead of a [``](https://reactnative.dev/docs/view) to account for safe areas automatically in your screen components. Using the library, the result of the previous example changes as it displays the content inside a safe area, as shown below: ### Installation You can skip installing `react-native-safe-area-context` if you have created a project using [the default template](/get-started/create-a-project). This library is installed as peer dependency for Expo Router library. Otherwise, install it by running the following command: ```sh npx expo install react-native-safe-area-context ``` ### Usage You can directly use [`SafeAreaView`](https://appandflow.github.io/react-native-safe-area-context/api/safe-area-view) to wrap the content of your screen's component. It is a regular `` with the safe area insets applied as extra padding or margin. ```tsx import { Text } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function HomeScreen() { return ( Content is in safe area. ); } ``` Using a different Expo template and don't have Expo Router installed? Import and add [`SafeAreaProvider`](https://appandflow.github.io/react-native-safe-area-context/api/safe-area-provider) to the root component file (such as **App.tsx**) before using `SafeAreaView` in your screen component. ```tsx import { SafeAreaProvider } from 'react-native-safe-area-context'; export default function App() { return ( return ...; ); } ``` ## Alternate: `useSafeAreaInsets` hook Alternate to `SafeAreaView`, you can use [`useSafeAreaInsets`](https://appandflow.github.io/react-native-safe-area-context/api/use-safe-area-insets) hook in your screen component. It provides direct access to the safe area insets, allowing you to apply padding for each edge of the `` using an inset from this hook. The example below uses the `useSafeAreaInsets` hook. It applies top padding to a `` using `insets.top`. ```tsx import { Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; export default function HomeScreen() { const insets = useSafeAreaInsets(); return ( Content is in safe area. ); } ``` The hook provides the insets in the following object: ```ts { top: number, right: number, bottom: number, left: number } ``` ## Additional information ### Minimal example Below is a minimal working example that uses the `useSafeAreaInsets` hook to apply top padding to a view. ```tsx import { Text, View } from 'react-native'; import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; function HomeScreen() { const insets = useSafeAreaInsets(); return ( Content is in safe area. ); } export default function App() { return ( ); } ``` ### Usage with React Navigation By default, React Navigation supports safe areas and uses `react-native-safe-area-context` as a peer dependency. For more information, see the [React Navigation documentation](https://reactnavigation.org/docs/handling-safe-area/). ### Usage with web If you are targeting the web, set up `SafeAreaProvider` as described in the [usage section](/develop/user-interface/safe-areas#usage). If you are doing server-side rendering (SSR), see the [Web SSR section](https://appandflow.github.io/react-native-safe-area-context/optimizations#web-ssr) in the library's documentation. --- --- modificationDate: February 25, 2026 title: System bars description: Learn how to handle and customize system bars for safe areas and edge-to-edge layout in your Expo project. --- # System bars Learn how to handle and customize system bars for safe areas and edge-to-edge layout in your Expo project. System bars are the UI elements at the edges of the screen that provide essential device information and navigation controls. Depending on the mobile OS, they include the status bar ([Android](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars) and [iOS](https://developer.apple.com/design/human-interface-guidelines/status-bars)), caption bar ([Android](https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b#:~:text=or%20SHORT_EDGES.-,Caption%20bars,-When%20your%20app) only), navigation bar ([Android](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars#navigation-bar) and [iOS](https://developer.apple.com/design/human-interface-guidelines/navigation-bars)), and home indicator (iOS only). These components are used to display device information such as battery level, time, notification alerts, and provide direct interaction with the device from anywhere in the device's interface. For example, an app user can pull down the status bar to access quick settings and notifications regardless of which app they're currently using. System bars are fundamental to the mobile experience, and understanding how to work with them properly is important for creating your app. ## Handling overlaps using safe areas Some of your app's content may draw behind the system bars. To handle this, you need to position your app's content correctly by avoiding the overlap and ensuring that the controls from the system bars are present. The following guide walks you through how to use `SafeAreaView` or a hook to apply insets directly for each edge of the screen. [Safe areas](/develop/user-interface/safe-areas) — Learn how to add safe areas for screen components inside your Expo project. ### Safe areas and edge-to-edge layout on Android Before [edge-to-edge on Android](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android), it was common to have a translucent status bar and navigation bar. With this approach, the content drawn behind these bars was already underneath them, and it was typically not necessary to factor in safe areas. Now, [with edge-to-edge on Android](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android), you will need to use safe areas to ensure that content does not overlap with system bars. ## Customizing system bars System bars can be customized to match your app's design and provide better visibility in different scenarios. When using Expo, there are two libraries available for this: `expo-status-bar` and `expo-navigation-bar` (Android only). ### Status bar configuration The status bar appears at the top of the screen on both Android and iOS. You can customize it using [`expo-status-bar`](/versions/latest/sdk/status-bar). It provides a `StatusBar` component that you can use to control the appearance of the status bar while your app is running using the [`style`](/versions/latest/sdk/status-bar#style) property or the [`setStatusBarStyle`](/versions/latest/sdk/status-bar#statusbarsetstatusbarstylestyle-animated) method: ```tsx import { StatusBar } from 'expo-status-bar'; export default function RootLayout() { <> {/* Use light text instead of dark text in the status bar to provide more contrast with a dark background. */} ; } ``` > **Note:** In Expo default template, the `style` property is set to `auto`. It automatically picks the appropriate style depending on the color scheme (light or dark mode) currently used by your app. To control the `StatusBar` visibility, you can set the [`hidden`](/versions/latest/sdk/status-bar#hidden) property to `true` or use the [`setStatusBarHidden`](/versions/latest/sdk/status-bar#statusbarsetstatusbarhiddenhidden-animation) method. **With edge-to-edge enabled on Android, features from `expo-status-bar` that depend on an opaque status bar [are unavailable](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge)**. It's only possible to customize the style and visibility. Other properties will no-op and warn. ### Navigation bar configuration (Android only) On Android devices, the Navigation Bar appears at the bottom of the screen. You can customize it using the [`expo-navigation-bar`](/versions/latest/sdk/navigation-bar) library. It provides a `NavigationBar` component that you can use to set the style of the navigation bar using the [`setStyle`](/versions/latest/sdk/navigation-bar#navigationbarsetstylestyle) method: ```tsx import { Platform } from 'react-native'; import * as NavigationBar from 'expo-navigation-bar'; import { useEffect } from 'react'; useEffect(() => { if (Platform.OS === 'android') { // Set the navigation bar style NavigationBar.setStyle('dark'); } }, []); ``` To control the `NavigationBar` visibility, you can use the [`setVisibilityAsync`](/versions/latest/sdk/navigation-bar#navigationbarsetvisibilityasyncvisibility) method. **With edge-to-edge enabled on Android, features from `expo-navigation-bar` that depend on an opaque navigation bar [are unavailable](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge)**. It's only possible to customize the style and visibility. Other properties will no-op and warn. --- --- modificationDate: February 25, 2026 title: Fonts description: Learn how to integrate custom fonts in your app using local files or Google Font packages --- # Fonts Learn how to integrate custom fonts in your app using local files or Google Font packages Android and iOS come with their own set of platform fonts. To provide a consistent user experience and enhance your app's branding, you can use custom fonts. This guide covers different ways you can add and load a custom font into your project and also provides additional information related to fonts. ## Add a custom font There are two ways you can add a custom font into your project: - Add a font file into your local assets. For example, a font file in the **assets/fonts** directory. - Install a Google Font package. For example, installing [`@expo-google-fonts/inter`](https://www.npmjs.com/package/@expo-google-fonts/inter) package. ### Supported font formats Expo SDK officially supports OTF and TTF font formats across Android, iOS and web platforms. If your font is in another font format, you have to set up advanced configuration to support that format in your project. ### Variable fonts Variable fonts, including variable font implementations in OTF and TTF, do not have support across all platforms. For full platform support, use static fonts. Alternatively, use a utility such as [fontTools](https://fonttools.readthedocs.io/en/latest/varLib/mutator.html) to extract the specific axis configuration you want to use from the variable font and save it as a separate font file. ### How to choose between OTF and TTF If the font you're using has both OTF and TTF versions, prefer OTF. The **.otf** files are smaller than **.ttf** files. Sometimes, OTF also renders slightly better in certain contexts. ## Use a local font file Copy the file into your project's **assets/fonts** directory. > **assets/fonts** directory path is a common convention in React Native apps to put font files. You can place these files elsewhere if you follow a custom convention. Two ways to use the local font file in your project: - Embed the font file with [`expo-font` config plugin](/versions/latest/sdk/font#configuration-in-app-config) (Android and iOS only). - Load the font file with [`useFonts`](/versions/latest/sdk/font#usefontsmap) hook at runtime (Android, iOS, and web). ### With `expo-font` config plugin The `expo-font` config plugin allows embedding one or more font files in your project's native code. It supports `ttf` and `otf` for both Android and iOS, and `woff` and `woff2` are supported on iOS only. > **Note:** Config plugins only run on native platforms (Android and iOS). For web, use the [`useFonts` hook](/develop/user-interface/fonts#with-usefonts-hook) instead. This is the recommended method for adding fonts to your app due to its benefits: - Fonts are available immediately when the app starts on a device. - No additional code required to load fonts in a project asynchronously when the app starts. - Fonts are consistently available across all devices where the app is installed because they're bundled within the app. However, this method also has some limitations: - Doesn't work with Expo Go since this method requires [creating a development build](/develop/development-builds/create-a-build). To embed a font in a project, follow the steps below: After adding a custom font file in your project, install the `expo-font` library. ```sh npx expo install expo-font ``` Add the config plugin to your [app config](/versions/latest/config/app#plugins) file. The configuration must contain the path to the font file using [`fonts`, `android` or `ios`](/versions/latest/sdk/font#configurable-properties) properties which take an array of one or more font definitions. The path to each font file is relative to the project's root. The example below showcases all valid ways a font can be specified: as an array of objects that specify `fontFamily` and other properties, or an array of paths to font files. For Android, you can specify the `fontFamily`, `weight`, and optionally `style` (defaults to `"normal"`), which will embed the fonts as native [XML resources](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml). If you provide only the font file paths in an array, the file name becomes the font family name on Android. iOS always extracts the font family name from the font file itself. If you plan to refer to fonts using just the `fontFamily`, provide an array of font paths (see `FiraSans-MediumItalic.ttf` below) and follow our [recommendation for file naming](/develop/user-interface/fonts#how-to-determine-which-font-family-name-to-use). If you want to refer to fonts using a combination of `fontFamily`, `weight`, and `style`, provide an array of objects (see `Inter` below). ```json { "expo": { "plugins": [ [ "expo-font", { "fonts": [ "./assets/fonts/FiraSans-MediumItalic.ttf" ], "android": { "fonts": [ { "fontFamily": "Inter", "fontDefinitions": [ { "path": "./assets/fonts/Inter-BoldItalic.ttf", "weight": 700, "style": "italic" }, { "path": "./assets/fonts/Inter-Bold.ttf", "weight": 700 } ] } ] }, "ios": { "fonts": ["./assets/fonts/Inter-Bold.ttf", "./assets/fonts/Inter-BoldItalic.ttf"] } } ] ] } } ``` After embedding the font with the config plugin, create a [new development build](/develop/development-builds/create-a-build) and install it on your device or Android Emulator or iOS Simulator. You can use the font with `` by specifying the `fontFamily` style prop. The examples below correspond to the fonts defined in the configuration above. ```tsx Inter Bold Inter Bold Italic Fira Sans Medium Italic ``` Using this method in an existing React Native project? - **Android:** Copy font files to **android/app/src/main/assets/fonts**. - **iOS:** See [Adding a Custom Font to Your App](https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app) in the Apple Developer documentation. #### How to determine which font family name to use - If you provide fonts as an array of file paths (as described above), on Android, the file name (without the extension) becomes the font family name. On iOS, the font family name is read from the font file itself. We recommend naming the font file same as its [PostScript name](/develop/user-interface/fonts#what-is-postscript-name-of-a-font) so the font family name is consistent on both platforms. - If you use the object syntax, provide the "Family Name". This can be found in the Font Book app on macOS, [fontdrop.info](https://fontdrop.info/) or other programs. What is PostScript name of a font file? The **PostScript name** of a font file is a unique identifier assigned to the font that follows Adobe's PostScript standard. It is used by operating systems and apps to refer to the font. It is not a font's **display name**. For example, Inter Black font file's PostScript name is `Inter-Black`. _Screenshot from Font Book app on macOS._ ### With `useFonts` hook The `useFonts` hook from `expo-font` library allows loading the font file asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized. It works with all Expo SDK versions and with Expo Go. To load a font in a project using `useFonts` hook, follow the steps below: After adding a custom font file in your project, install the `expo-font` and `expo-splash-screen` libraries. ```sh npx expo install expo-font expo-splash-screen ``` The [`expo-splash-screen`](/versions/latest/sdk/splash-screen) library provides `SplashScreen` component that you can use to prevent rendering the app until the font is loaded and ready. Map the font file using the `useFonts` hook in a top level component such as the root layout (**app/layout.tsx**) file in your project: ```tsx import { useFonts } from 'expo-font'; import * as SplashScreen from 'expo-splash-screen'; import {useEffect} from 'react'; SplashScreen.preventAutoHideAsync(); export default function RootLayout() { const [loaded, error] = useFonts({ 'Inter-Black': require('./assets/fonts/Inter-Black.otf'), }); useEffect(() => { if (loaded || error) { SplashScreen.hideAsync(); } }, [loaded, error]); if (!loaded && !error) { return null; } return ( ... ) } ``` Use the font on the `` by using `fontFamily` style prop in a React component: ```tsx Inter Black ``` ## Use Google Fonts Expo has first-class support for all fonts listed in [Google Fonts](https://fonts.google.com/). They are available using [`@expo-google-fonts`](https://github.com/expo/google-fonts) library. With any of the font package from this library, you can quickly integrate that font and its variants. Two ways to use a Google Font in your project: - Embed the installed font with [`expo-font` config plugin](/versions/latest/sdk/font#configuration-in-appjsonappconfigjs). - Load the installed font with [`useFonts`](/versions/latest/sdk/font#usefontsmap) hook at runtime asynchronously. ### With `expo-font` config plugin > **Note:** Embedding a Google Font using `expo-font` config plugin has same benefits and limitations as embedding a custom font on your own. See [using a local font file with `expo-font` config plugin](/develop/user-interface/fonts#with-expo-font-config-plugin) for more information. Install the font package. For example, to use Inter Black font, install the [`@expo-google-fonts/inter`](https://www.npmjs.com/package/@expo-google-fonts/inter) package with the command below. ```sh npx expo install expo-font @expo-google-fonts/inter ``` Add the config plugin to your [app config](/versions/latest/config/app#plugins) file. The configuration must contain the path to the font file using [`fonts`](/versions/latest/sdk/font#configurable-properties) property which takes an array of one or more font files. The path to the font file is defined from the font package inside the `node_modules` directory. For example, if you have a font package named `@expo-google-fonts/inter`, then the name of the file is **Inter_900Black.ttf**. ```json { "plugins": [ [ "expo-font", { "fonts": ["node_modules/@expo-google-fonts/inter/900Black/Inter_900Black.ttf"] } ] ] } ``` After embedding the font with the config plugin, create a [new development build](/develop/development-builds/create-a-build) and install it on your device or Android Emulator or iOS Simulator. On Android, you can use the font file name. For example, `Inter_900Black`. On iOS, use the font and its weight name ([PostScript name](/develop/user-interface/fonts#what-is-postscript-name-of-a-font)). The example below demonstrates how to use [`Platform`](https://reactnative.dev/docs/platform-specific-code#platform-module) to select the correct font family name for each platform: ```tsx import { Platform } from 'react-native'; // Inside a React component: Inter Black ``` ### With `useFonts` hook > **Note:** Loading a Google Font using `useFonts` hook has same benefits and limitations as embedding a custom font on your own. See [using a local font file with `useFonts` hook](/develop/user-interface/fonts#with-usefonts-hook) for more information. Each google Fonts package provides the `useFonts` hook to load the fonts asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized. The font package also imports the font file so you don't have to explicitly import it. Install the Google Fonts package, `expo-font` and `expo-splash-screen` libraries. ```sh npx expo install @expo-google-fonts/inter expo-font expo-splash-screen ``` The [`expo-splash-screen`](/versions/latest/sdk/splash-screen) library provides `SplashScreen` component that you can use to prevent rendering the app until the font is loaded and ready. After installing the font package, map the font using the `useFonts` hook in a top level component such as the root layout (**app/layout.tsx**) file in your project: ```tsx // Rest of the import statements import { Inter_900Black, useFonts } from '@expo-google-fonts/inter'; import * as SplashScreen from 'expo-splash-screen'; import {useEffect} from 'react'; SplashScreen.preventAutoHideAsync(); export default function RootLayout() { const [loaded, error] = useFonts({ Inter_900Black, }); useEffect(() => { if (loaded || error) { SplashScreen.hideAsync(); } }, [loaded, error]); if (!loaded && !error) { return null; } return ( ... ) } ``` Use the font on the `` by using `fontFamily` style prop in a React component: ```tsx Inter Black ``` ## Additional information ### Minimal example [expo-font usage](/versions/latest/sdk/font#usage) — expo-font — See usage section in Expo Fonts API reference for a minimal example of using a custom font. ### Beyond OTF and TTF If your font is in format other than OTF or TTF, you have to [customize the Metro bundler configuration to include it as an extra asset](/guides/customizing-metro#adding-more-file-extensions-to-assetexts) for it to work. In some cases, rendering a font format that a platform doesn't support may cause your app to crash. For reference, the following table provides the list formats that work on each native platform: | Format | Android | iOS | Web | | --- | --- | --- | --- | | bdf | ✗ | ✗ | ✗ | | dfont | ✓ | ✗ | ✗ | | eot | ✗ | ✗ | ✓ | | fon | ✗ | ✗ | ✗ | | otf | ✓ | ✓ | ✓ | | ps | ✗ | ✗ | ✗ | | svg | ✗ | ✗ | ✓ | | ttc | ✗ | ✗ | ✗ | | ttf | ✓ | ✓ | ✓ | | woff | ✗ | ✓ | ✓ | | woff2 | ✗ | ✓ | ✓ | ### Platform built-in fonts If you don't want to use a custom font by specifying a `fontFamily`, platform's default font will be used. Each platform has a set of built in fonts. On Android, the default font is Roboto. On iOS, it's SF Pro. A platform's default font is usually easy-to-read. However, don't be surprised when the system default font is changed to use another font that is not easy to read. In this case, use your custom font so you have precise control over what the user will see. ### Handle `@expo/vector-icons` initial load When the icons from `@expo/vector-icons` library load for the first time, they appear as invisible icons in your app. Once they load, they're cached for all the app's subsequent usage. To avoid showing invisible icons on your app's first load, preload during the initial loading screen with [`useFonts`](/versions/latest/sdk/font#usefontsmap). For example: ```tsx import { useFonts } from 'expo-font'; import Ionicons from '@expo/vector-icons/Ionicons'; export default function RootLayout() { useFonts([require('./assets/fonts/Inter-Black.otf', Ionicons.font)]); return ( ... ) } ``` Now, you can use any icon from the `Ionicons` library in a React component: ```tsx ``` [Icons](/guides/icons) — Learn how to use various types of icons in your Expo app, including vector icons, custom icon fonts, icon images, and icon buttons. ### Loading a remote font directly from the web > **If you're loading remote fonts, make sure they are being served from an origin with CORS properly configured**. If you don't do this, your remote font might not load properly on the web platform. Loading fonts from a local asset is the safest way to load a font in your app. When including fonts as local assets, after you submit your app to the app stores, these fonts are bundled with the app download and will be available immediately. You don't have to worry about CORS or other potential issues. However, loading a font file directly from web is done by replacing the `require('./assets/fonts/FontName.otf')` with the URL of your font as shown in the example below. ```tsx import { useFonts } from 'expo-font'; import { Text, View, StyleSheet } from 'react-native'; export default function App() { const [loaded, error] = useFonts({ 'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12', }); if (!loaded || !error) { return null; } return ( Inter SemiBoldItalic Platform Default ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` --- --- modificationDate: February 25, 2026 title: Assets description: Learn about using static assets in your project, including images, videos, sounds, database files, and fonts. --- # Assets Learn about using static assets in your project, including images, videos, sounds, database files, and fonts. A **static asset** is a file that is bundled with your app's binary (native binary). This file type is not part of your app's JavaScript bundle which contain your app's code. Common types of static assets include images, videos, sounds, database files for SQLite, and fonts. These assets can be served locally from your project or remotely over the network. This guide covers different ways you can load and use static assets in your project and also provides additional information on how to optimize and minify assets. ## Serve an asset locally When an asset is stored in your project's file system, it can be embedded in your app binary at build time or loaded at runtime. You can import it like a JavaScript module using `require` or `import` statements. For example, to render an image called **example.png** in **App.js**, you can use `require` to import the image from the project's **assets/images** directory and pass it to the `` component: ```tsx ``` In the above example, the bundler reads the imported image's metadata and automatically provides the width and height. For more information, see [Static Image Resources](https://reactnative.dev/docs/images#static-image-resources). Libraries such as `expo-image` and `expo-file-system` work similarly to the `` component with local assets. ### How are assets served locally Locally stored assets are served over HTTP in development. They are automatically bundled into your app binary at the build time for production apps and served from disk on a device. ### Load an asset at build time with `expo-asset` config plugin To load an asset at build time, you can use the [config plugin](/versions/latest/sdk/asset#example-appjson-with-config-plugin) from the `expo-asset` library. This plugin will embed the asset file in your native project. Install the `expo-asset` library. ```sh npx expo install expo-asset ``` Add the config plugin to your project's [app config](/versions/latest/config/app#plugins) file. The configuration must contain the path to the asset file using [`assets`](/versions/latest/sdk/asset#configurable-properties) property which takes an array of one or more files or directories to link to the native project. The path to each asset file must be relative to your project's root since the app config file is located in the project's root directory. ```json { "expo": { "plugins": [ [ "expo-asset", { "assets": ["./assets/images/example.png"] } ] ] } } ``` After embedding the asset with the config plugin, [create a new development build](/develop/development-builds/create-a-build). Now, you can import and use the asset in your project without using a `require` or an `import` statement. For example, the **example.png** is linked by the above config plugin. You can directly import it into your component and use its resource name as the URI. Note that when rendering assets without using `require`, you need to explicitly provide a width / height. ```tsx import { Image } from 'expo-image'; ... export default function HomeScreen() { return ; } ``` > Different file formats are supported with the `expo-asset` config plugin. For more information on these formats, see [Assets API reference](/versions/latest/sdk/asset#configurable-properties). If you don't see a file format supported by the config plugin, you can use the [`useAssets`](/develop/user-interface/assets#load-an-asset-at-runtime-with-useassets-hook) hook to load the asset at runtime. ### Load an asset at runtime with `useAssets` hook The `useAssets` hook from `expo-asset` library allows loading assets asynchronously. This hook downloads and stores an asset locally and after the asset is loaded, it returns a list of that asset's instances. Install the `expo-asset` library. ```sh npx expo install expo-asset ``` Import the [`useAssets`](/versions/latest/sdk/asset#useassetsmoduleids) hook from the `expo-asset` library in your screen component: ```tsx import { useAssets } from 'expo-asset'; export default function HomeScreen() { const [assets, error] = useAssets([ require('path/to/example-1.jpg'), require('path/to/example-2.png'), ]); return assets ? : null; } ``` ## Serve an asset remotely When an asset is served remotely, it is not bundled into the app binary at build time. You can use the URL of the asset resource in your project if it is hosted remotely. For example, pass the URL to the `` component to render a remote image: ```jsx import { Image } from 'expo-image'; ... function App() { return ( ); } ``` There is no guarantee about the availability of images served remotely using a web URL because an internet connection may not be available, or the asset might be removed. Additionally, loading assets remotely also requires you to provide an asset's metadata. In the above example, since the bundler cannot retrieve the image's width and height, those values are passed explicitly to the `` component. If you don't, the image will default to 0px by 0px. ## Additional information ### Manual optimization methods #### Images You can compress images using the following: - [`guetzli`](https://github.com/google/guetzli) - [`pngcrush`](https://pmt.sourceforge.io/pngcrush/) - [`optipng`](http://optipng.sourceforge.net/) Some image optimizers are lossless. They re-encode your image to be smaller without any change or loss in the pixels displayed. When you need each pixel to be untouched from the original image, a lossless optimizer and a lossless image format like PNG are a good choice. Other image optimizers are lossy. The optimized image differs from the original image. Often, lossy optimizers are more efficient because they discard visual information that reduces file size while making the image look nearly identical to humans. Tools like `imagemagick` can use comparison algorithms like [SSIM](https://en.wikipedia.org/wiki/Structural_similarity) to show how similar two images look. It's quite common for an optimized image that is over 95% similar to the original image to be far less than 95% of the original file size. #### Other assets For assets like GIFs or videos, or non-code and non-image assets, it's up to you to optimize and minify those assets. > **Note**: GIFs are a very inefficient format. Modern video codecs can produce significantly smaller file sizes with better quality. ### Fonts See [Add a custom font](/develop/user-interface/fonts#add-a-custom-font) for more information on how to add a custom font to your app. --- --- modificationDate: February 25, 2026 title: Color themes description: Learn how to support light and dark modes in your app. --- # Color themes Learn how to support light and dark modes in your app. It's common for apps to support light and dark color schemes. Here is an example of how supporting both modes looks in an Expo project: ## Configuration > For Android and iOS projects, additional configuration is required to support switching between light and dark mode. For web, no additional configuration is required. To configure supported appearance styles, you can use the [`userInterfaceStyle`](/versions/latest/config/app#userinterfacestyle) property in your project's [app config](/versions/latest/config/app). By default, this property is set to `automatic` when you create a new project with the [default template](/get-started/create-a-project). Here is an example configuration: ```json { "expo": { "userInterfaceStyle": "automatic" } } ``` You can also configure `userInterfaceStyle` property for a specific platforms by setting either [`android.userInterfaceStyle`](/versions/latest/config/app#userinterfacestyle-2) or [`ios.userInterfaceStyle`](/versions/latest/config/app#userinterfacestyle-1) to the preferred value. > The app will default to the `light` style if this property is absent. When you are creating a development build, you have to install [`expo-system-ui`](/versions/latest/sdk/system-ui#installation) to support the appearance styles for Android. Otherwise, the `userInterfaceStyle` property is ignored. ```sh npx expo install expo-system-ui ``` If the project is misconfigured and doesn't have `expo-system-ui` installed, the following warning will be shown in the terminal: ```sh » android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature. ``` You can also use the following command to check if the project is misconfigured: ```sh npx expo config --type introspect ``` Using bare React Native app? #### Android Ensure that the `uiMode` flag is present on your `MainActivity` (and any other activities where this behavior is desired) in **AndroidManifest.xml**: ```xml ``` Implement the `onConfigurationChanged` method in **MainActivity.java**: ```java import android.content.Intent; import android.content.res.Configuration; public class MainActivity extends ReactActivity { ... @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Intent intent = new Intent("onConfigurationChanged"); intent.putExtra("newConfig", newConfig); sendBroadcast(intent); } ... } ``` #### iOS You can configure supported styles with the [`UIUserInterfaceStyle`](https://developer.apple.com/documentation/bundleresources/information_property_list/uiuserinterfacestyle) key in your app **Info.plist**. Use `Automatic` to support both light and dark modes. ### Supported appearance styles The `userInterfaceStyle` property supports the following values: - `automatic`: Follow system appearance settings and notify about any change the user makes. - `light`: Restrict the app to support light theme only. - `dark`: Restrict the app to support dark theme only. ## Detect the color scheme To detect the color scheme in your project, use `Appearance` or `useColorScheme` from `react-native`: ```tsx import { Appearance, useColorScheme } from 'react-native'; ``` Then, you can use `useColorScheme()` hook as shown below: ```tsx function MyComponent() { let colorScheme = useColorScheme(); if (colorScheme === 'dark') { // render some dark thing } else { // render some light thing } } ``` In some cases, you will find it helpful to get the current color scheme imperatively with [`Appearance.getColorScheme()` or listen to changes with `Appearance.addChangeListener()`](https://reactnative.dev/docs/appearance). ## Additional information ### Minimal example ```tsx import { Text, StyleSheet, View, useColorScheme } from 'react-native'; import { StatusBar } from 'expo-status-bar'; export default function App() { const colorScheme = useColorScheme(); const themeTextStyle = colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText; const themeContainerStyle = colorScheme === 'light' ? styles.lightContainer : styles.darkContainer; return ( Color scheme: {colorScheme} ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 20, }, lightContainer: { backgroundColor: '#d0d0c0', }, darkContainer: { backgroundColor: '#242c40', }, lightThemeText: { color: '#242c40', }, darkThemeText: { color: '#d0d0c0', }, }); ``` ### Tips While you are developing your project, you can change your simulator's or device's appearance by using the following shortcuts: - If using an Android Emulator, you can run `adb shell "cmd uimode night yes"` to enable dark mode, and `adb shell "cmd uimode night no"` to disable dark mode. - If using a physical Android device or an Android Emulator, you can toggle the system dark mode setting in the device's settings. - If working with an iOS emulator locally, you can use the Cmd ⌘ + Shift + a shortcut to toggle between light and dark modes. --- --- modificationDate: February 25, 2026 title: Animation description: Learn how to integrate React Native animations and use it in your Expo project. --- # Animation Learn how to integrate React Native animations and use it in your Expo project. Animations are a great way to enhance and provide a better user experience. In your Expo projects, you can use the [Animated API](https://reactnative.dev/docs/next/animations) from React Native. However, if you want to use more advanced animations with better performance, you can use the [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/) library. It provides an API that simplifies the process of creating smooth, powerful, and maintainable animations. ## Installation You can skip installing `react-native-reanimated` if you have created a project using [the default template](/get-started/create-a-project). This library is already installed. Otherwise, install it by running the following command: ```sh npx expo install react-native-reanimated ``` ## Usage ### Minimal example The following example shows how to use the `react-native-reanimated` library to create a simple animation. For more information on the API and advanced usage, see [`react-native-reanimated` documentation](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/your-first-animation). ```tsx import Animated, { useSharedValue, withTiming, useAnimatedStyle, Easing, } from 'react-native-reanimated'; import { View, Button, StyleSheet } from 'react-native'; export default function AnimatedStyleUpdateExample() { const randomWidth = useSharedValue(10); const config = { duration: 500, easing: Easing.bezier(0.5, 0.01, 0, 1), }; const style = useAnimatedStyle(() => { return { width: withTiming(randomWidth.value, config), }; }); return (