How To Publish Expo React Native App to iOS and Android

Introduction
Distributing (or publishing) the Expo React Native app to stores is always a critical and painful process in the development application.
In this article, I would like to guide you through the whole process of publishing the Expo app, from the beginning to the moment you can download it from the store.
I will show you:
- how to build standalone apps,
- what are the requirements and app signings
- and other important things which will make the publishing process easier.
In this tutorial, we are going to use Expo for both building and publishing the app. Remember, that if you would have any problems with that, you can consider to outsource React Native development to an experienced agency.
Requirements
First of all, you will need developer accounts.
An Apple Developer account is needed to build an iOS standalone app, and to publish it to the stores.
In case of Android, It looks a bit different. You need a developer account only to submit an app to the store, and it is not required to build it.
Developers accounts:
- iOS – build and publish app
- Android – publish app
To build apps we need expo-cli. So if you haven’t installed it yet – go and do it now!
Build app – managed workflow
The first step before publishing the Expo app is adding the build information to the app.json file.
The required items are: name, icon and version. You also have to add a bundle identifier and build number for iOS and package name and version code for android apps.
The Expo team suggests adding also slug – it represents a piece of url for our app. You can add more information to app.json
(like release channels) but describe only the ones required.
Example:
{
"expo": {
"name": "test-publish-app",
"slug": "test-publish-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splassh.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": ["**/*"],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.pagepro.testpublishapp",
"buildNumber": "1.0.0"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
},
"package": "com.pagepro.testpublishapp",
"versionCode": 1
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}
Build app
If you have filled things correctly in the app.json, the next step in publishing the Expo app is triggering the build application by running expo-cli.
Run expo build to build apps for both environments or specify one by adding Android, iOS platform.
expo build //build app for both platforms
expo build:android //build app for android
expo build:ios //build app for ios
Building app – Android
If you are building an app for android, you have 2 options – build APK or Android App Bundle.
I recommend using the second option, just make sure Google Play App Signing is enabled for building projects.
Google Play App Signing
When you build the application for the first time, you will be asked whether you upload a keystore file or have the Expo team handle it for you.
No matter what option you choose, backup that keystore to a safe location.
If you want to update the application in future you will need that keystore – every future update to Google Play Store must be signed with that to be accepted by Google.
Build process in details
Step 1: Run expo build:android and choose apk-bundle option:

Step 2: Generate keystore file or update existing one. I don’t have any, so I let Expo create a new one:

Step 3: After the keystore is created, it should run the build:

Step 4: If everything goes fine, the terminal should paste an URL to the build. Go there and download an artifact. We will need it later to put the app in store:

Building app – iOS
The situation is similar to Android here.
You can build apps in two different types, like an archive or a simulator.
The first one allows users to publish an app to AppStore or TestFlight, and the second one is only for testing purposes on a simulator.
iOS Credentials
In case of Apple apps, they need credentials in order to be built and published.
Expo can create necessary credentials for you. All you need to do is to sign in your Apple Developer account. Don’t worry about passing it to Expo CLI, it is used locally and is never saved on Expo’s servers.
If you want to create that credentials by yourself, you have to do it on Apple Developer Portal.
App Signing – description of credentials
Expo can automatically sign your app for iOS and Android. If you don’t want help from the Expo team, you have to do it by yourself. You will have some requirements that you must do if you want to push your application to the store.
iOS
There are 3 required credentials you have to do by Apple Developer account:
- Distribution Certificate – this is a certificate that tells everything about a developer. You may only have one distribution certificate associated with your Apple Developer account. This certificate will be used for all of your apps. If that certificate expired you cannot update your apps anymore.
- Provisioning Profile – this is a certificate which is app-specific (each certificate for every app). That certificate is associated with the distribution certificate. If the distribution certificate expires – you have to renew provisioning too. Provisioning profiles expire after 12 months.
- Push Notification Keys – that keys are related with push notifications, and it’s required by Expo. The reason is you can later enable push notification in the app by OTA updates, rather than submit it by store.
Summary in details

Clear Credentials
You can remove your credentials by running remove commands – expo build:ios –clear-credentials – this only removes credentials from Expo’s servers, it does not delete the credentials from Apple’s perspective. To remove it successfully, you have to go to Apple Developer Console and do it manually.
Android
This is easier than on iOS env. Google requires all Android apps to be digitally signed with a certificate before they are installed on a device or updated.
Check status
After running commands, Expo builds it on their servers. Of course, you can check the progress status and track build logs on the portal or by running expo build:status.
When build is done, you will see the url to your app file – paste it to the browser immediately and download the bundle of apps.
WANT TO BUILD A REACT NATIVE APP?
Build process in details
Step 1: Run expo build:iOS and choose archive option:

Step 2: Expo-cli asked you about sign in to Apple developer account. Pass credentials and log in:

Step 3: Then you need to verify your Apple account:

Step 4: If you successfully log in, you need to select a team:

Step 5: Creating iOS Certificates.
You can do it by yourself on Apple Developer Account or let Expo do that. I chose a second option.


Step 6: After that steps, build should run:

Step 7: If everything went fine, expo-cli shows a URL you can download an archive, do that – we will need it to next publish steps:

Best practices about Deploying App to Stores
If you want to ensure your app satisfies the assumptions and will be accepted to the Apple and Google shops, try to take care of some of these:
- add a splash screen, the first thing users see after he runs an app,
- preload and cache assets so app loads quickly,
- define correct status bar to work correct with your UI,
- use native gestures whenever possible,
- add a great icon that pass environment requirements,
- make sure your app got valid identifiers,
- make sure your app has got valid versioning,
- adding privacy policy,
- pass iOS specific guidelines [link].
Deploying to App Stores
This is the last step of publishing – putting applications into stores.
That will help you upload your standalone apps to Apple TestFlight or Google Play. As I mentioned earlier, you will need developer accounts for this. So if you don’t have them yet, you need to go to Apple Developer and Google Play Developer site to buy them.
The first upload is required to do manually for both Apple and Android. I will show that process later.
Next time we upload an app to stores, we will use an expo CLI and these commands:
expo upload:android // submit android app
expo upload:ios // submit iOS app
Status on 24.04.2021:

Command expo upload:ios are not available anymore. Expo team recommended use:
Transporter, EAS Submit, Fastlane Deliver

EAS Submit is still a premium option, and you need to pay for Expo Premium Account to use it.
So the free option for iOS is manually put via Transporter or XCode.
Deploy in details – Android
For the first time, you have to upload an application manually. I will show a short guide explaining that process.
Setup Google Store
Step 1: Go to Google Play Console and create a new account to get access to API interface.
If you’d like to submit your Android app to Google Play Store with expo upload:android or eas submit, you need to do this:








Step 2: Create a new application.
The first app upload needs to be done manually.







Step 3: After submitting the test version, you should probably get an error.
You need to go to rules and pass a URL to the privacy policy.


Step 4: When you come back to the application tab, errors should disappear, and now you can submit the app.






Step 5: After submission, you have to add testers which have got access to download and use the app.



Step 6: After that, you should get access to the test application via the store.
Next time, you can upload and update the app using expo-cli.


Deploy in details – iOS
You can build an iOS app only on macOS. So if you want to upload an iOS app to the App Store, you will need to have a macOS device or use a virtual machine and install OSX on it.
Here the situation is so different than with Android. First, you don’t have to do the first upload manually. You can use expo-cli. In fact, you can use expo CLI right away by running expo upload:ios. In that case, you need 2 required flags with commands:
--apple-id - your Apple ID login
--apple-id-password - your Apple ID password.
After running that command, if everything went well, it should publish this application to TestFlight.
Setup Apple Connect
Step 1: Go to Apple Store Connect and create an application.

Step 2: Fill in the details about the application.
Set a bundle ID that you filled in app.json.

Step 3: Download artifact from Expo servers, you will send to connect.


Step 4: To put our app manually to TestFlight, we will need to use a Transporter application (available on the AppStore).
Manually upload instructions:
- Sign in into iTunes connect with your Apple ID and accept terms.
- Sign in to the Transporter app (use Apple ID).
- Add the IPA file with application to the Transporter.
- Submit the app by clicking the Deliver button.
This process can take a few minutes. After this process is complete, you can check the status of a submission to TestFlight in App Store Connect.

Step 5: After sending it via the Transporter app, you have to go back to the Apple Connect Store and submit that application.

Step 6: If you clicked the submit button, probably you have got some errors.
Don’t worry, it is normal. You have to refill information about the privacy policy.


Step 7: The last step is to wait for the application to be approved and add it to the TestFlight.

Conclusion
The process of building and publishing React Native apps to the stores isn’t easy, and you need some knowledge of so that.
I hope this article will help you go through that horrible part of the development process 🙂
The process describes publishing an expo app, which is a bit simplified due to the possibility of expo-cli.
But these are also some parts like setting up stores, uploading the app manually, or describing what certificates mean.