How to Use EAS Build Profiles Correctly
EAS Build profiles explained: development, preview, production. The env var story, the submit story, and the mistakes I stopped making.
EAS Build profiles explained: development, preview, production. The env var story, the submit story, and the mistakes I stopped making.
EAS Build profiles explained end-to-end: dev, preview, production, env vars, autoIncrement, submit config, and the mistakes I stopped making.
Prerequisites
If you only ever run eas build with no profile, you will eventually ship a dev build to TestFlight or wonder why your production env vars are not set. Profiles are the config layer that makes this safe.
expo-dev-client. Debug JS, dev menu, hot reload.eas.json I actually ship{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": { "EXPO_PUBLIC_API_URL": "http://localhost:3000" }
},
"preview": {
"distribution": "internal",
"env": { "EXPO_PUBLIC_API_URL": "https://staging.api.yourapp.com" },
"channel": "preview"
},
"production": {
"autoIncrement": true,
"env": { "EXPO_PUBLIC_API_URL": "https://api.yourapp.com" },
"channel": "production"
}
}
}
autoIncrement on production is worth the toggleSet autoIncrement: true on the production profile. EAS bumps buildNumber (iOS) and versionCode (Android) automatically every build. If you forget to bump manually, App Store Connect rejects the upload. This is the single line that prevents that.
EXPO_PUBLIC_* env vars are baked into the JS bundle at build time. Change them in eas.json.process.env in production for anything except EXPO_PUBLIC_*.Add a submit block to eas.json:
{
"submit": {
"production": {
"ios": {
"appleId": "you@example.com",
"ascAppId": "1234567890",
"appleTeamId": "XXXXXXXXXX"
},
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "internal"
}
}
}
}
Now eas submit -p ios --profile production does the upload. No manual drag into Transporter.
channel: Without it, OTA updates from expo-updates go to a default channel and mix preview with production. Set the channel explicitly on every profile.com.yourapp.dev).eas.json: Never commit secrets. Use eas secret:create for anything sensitive.AI App Factory ships eas.json with all three profiles, separated bundle ids for dev, channel config, and a pre-wired submit block. You edit domain and team id.
Everything in this guide is already pre-configured in AI App Factory. 11 AI agents automate the rest.