Section 5 · Shipping
Building and Submitting with EAS
18 min3 min readPut in order
Lesson at a glance
Configure Trailhead’s identity and versions, create development, preview and production builds with EAS Build, send them to TestFlight and Google Play with EAS Submit, and prepare for app review.
- 1Identity and versions in app.json
- 2Build profiles
- 3Credentials
- 4Submitting to the stores
- 5Getting through review
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
So far Trailhead has run through Expo Go and development builds, with your laptop serving the JavaScript. Real users need something else: an app that installs from a store, starts without a dev server, and is signed so their phone trusts it. EAS Build makes those builds in the cloud, so you don’t need a Mac for iOS, and EAS Submit uploads them to the stores.
Identity and versions in app.json
Before the first build, settle a few fields:
{
"expo": {
"name": "Trailhead",
"slug": "trailhead",
"version": "1.0.0",
"scheme": "trailhead",
"icon": "./assets/images/icon.png",
"ios": { "bundleIdentifier": "com.example.trailhead" },
"android": { "package": "com.example.trailhead" }
}
}The bundle identifier (iOS) and package name (Android) are your app’s permanent identity in the stores. Change them after publishing and the store sees a different app: no updates for existing users, no reviews carried over. Use a reverse domain you control.
There are two kinds of version. version is what users see (“1.0.0”); you raise it for each public release. Each upload also needs a unique, increasing internal number (the iOS build number and Android version code). Let EAS manage those for you, as shown below.
Build profiles
Install the CLI, sign in to your Expo account and generate the config:
npm install -g eas-cli
eas login
eas build:configureThat creates eas.json with three profiles:
{
"cli": { "appVersionSource": "remote" },
"build": {
"development": { "developmentClient": true, "distribution": "internal" },
"preview": { "distribution": "internal" },
"production": { "autoIncrement": true }
},
"submit": { "production": {} }
}- development builds your own dev client (the development build from section 1), with the dev menu, loading JavaScript from Metro.
- preview builds a standalone app for testers, installed from a link or QR code (internal distribution). On iOS, testers’ devices must be registered first with
eas device:create, because these are ad hoc builds. - production builds for the stores. With
appVersionSource: "remote"andautoIncrement, EAS stores and raises the build number on every production build.
Then build:
eas build --platform android --profile preview
eas build --platform all --profile productionThe build runs on EAS servers; the CLI prints a link to the logs and, at the end, to the build itself.
Credentials
Every installable build is signed. iOS needs a distribution certificate and provisioning profile; Android needs an upload keystore. EAS can generate these, store them, and reuse them for every build; the CLI asks the first time. For iOS you need a paid Apple Developer Program membership; for Google Play, a one-time developer registration fee. Treat the Android keystore with care: EAS keeps it for you, but if you manage your own and lose it, updating the app gets painful.
Submitting to the stores
First create the app’s record in App Store Connect and in Google Play Console. Then upload the latest production build:
eas submit --platform ios
eas submit --platform androidOn iOS the build goes to App Store Connect, where it becomes available in TestFlight for testers after processing. On Android it lands on a testing track (internal by default); EAS needs a Google service account key to upload for you. You can combine both steps with eas build --auto-submit.
Getting through review
Both stores review apps, Apple more strictly. You’ll fill in a store listing (name, description, screenshots for required device sizes), a privacy policy URL, and privacy details: Apple’s App Privacy section and Google Play’s Data safety form, which must match what Trailhead actually collects, such as location and photos.
Reviews usually take from a few hours to a couple of days. Once approved, you choose when to release. Then the cycle repeats for every native change: new version, build, submit, review. For JavaScript-only fixes there’s a faster path, which is the final lesson.
Key takeaways
- A release build compiles the native app, bundles and minifies your JavaScript, and signs it with credentials the stores trust.
- The iOS bundle identifier and Android package name are permanent once you publish; choose them deliberately.
- eas.json profiles describe builds:
developmentfor your dev client,previewfor testers,productionfor the stores. eas submituploads a production build to App Store Connect or Google Play; testers get it through TestFlight or a testing track before review.- Most first rejections come from crashes, vague permission text, missing privacy details or no demo account for a sign-in-only app.