Building and deploying Expo React Native apps to iOS. Use when configuring EAS Build, submitting to TestFlight, App Store deployment, managing certificates, or troubleshooting build issues.
# Install EAS CLI
npm install -g eas-cli
# Login to Expo account
eas login
# Initialize EAS in project
eas build:configure
This creates eas.json:
{
"cli": {
"version": ">= 5.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal"
},
"production": {}
},
"submit": {
"production": {}
}
}
{
"expo": {
"name": "MyApp",
"slug": "myapp",
"version": "1.0.0",
"scheme": "myapp",
"ios": {
"bundleIdentifier": "com.yourcompany.myapp",
"buildNumber": "1",
"supportsTablet": false,
"infoPlist": {
"NSCameraUsageDescription": "Take photos for your profile",
"NSLocationWhenInUseUsageDescription": "Find locations near you"
}
}
}
}
# For simulator
eas build --profile development --platform ios
# For physical device
eas build --profile development --platform ios --local
Use with npx expo start --dev-client
eas build --profile preview --platform ios
Distributes via ad-hoc provisioning. Testers install via link.
eas build --profile production --platform ios
EAS manages credentials automatically, but you can control them:
# View current credentials
eas credentials
# Let EAS manage everything (recommended)
# Just run build, it handles certificates
# Use existing credentials
eas credentials --platform ios
# Select "Use existing" and provide paths
eas.json:{
"build": {
"production": {
"ios": {
"credentialsSource": "local"
}
}
}
}
{
"build": {
"production": {
"env": {
"API_URL": "https://api.yourapp.com"
}
},
"preview": {
"env": {
"API_URL": "https://staging-api.yourapp.com"
}
}
}
}
# Set secret
eas secret:create --name API_KEY --value "sk_live_xxx" --scope project
# List secrets
eas secret:list
# Use in app.json
{
"extra": {
"apiKey": process.env.API_KEY
}
}
Access in code:
import Constants from 'expo-constants';
const apiKey = Constants.expoConfig?.extra?.apiKey;
{
"submit": {
"production": {
"ios": {
"appleId": "your@email.com",
"ascAppId": "1234567890",
"appleTeamId": "XXXXXXXXXX"
}
}
}
}
Get ascAppId from App Store Connect URL: https://appstoreconnect.apple.com/apps/1234567890
# Build and submit in one command
eas build --profile production --platform ios --auto-submit
# Or submit existing build
eas submit --platform ios --latest
# Submit specific build
eas submit --platform ios --id <build-id>
# Automated submission
eas submit --platform ios --latest
For JS/asset-only changes (no native code changes):
# Publish update
eas update --branch production --message "Bug fix for login"
# Preview before publishing
eas update --branch preview --message "Testing new feature"
{
"build": {
"production": {
"channel": "production"
},
"preview": {
"channel": "preview"
}
}
}
import * as Updates from 'expo-updates';
async function checkForUpdates() {
if (__DEV__) return; // Skip in development
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
}
} catch (error) {
console.log('Update check failed:', error);
}
}
{
"expo": {
"version": "1.1.0" // Shown to users
}
}
{
"expo": {
"ios": {
"buildNumber": "2" // Must increase for each upload
}
}
}
{
"build": {
"production": {
"ios": {
"autoIncrement": "buildNumber"
}
}
}
}
Build on your machine instead of EAS servers:
# Requires Xcode installed
eas build --platform ios --local
Useful for:
# Reset credentials and let EAS regenerate
eas credentials --platform ios
# Select "Remove" then rebuild
Add to app.json:
{
"expo": {
"ios": {
"infoPlist": {
"ITSAppUsesNonExemptEncryption": false
}
}
}
}
# Check native logs
eas build:view <build-id>
# Download and inspect build
eas build:download <build-id>
Updates.checkForUpdateAsync() is called# Build
eas build --platform ios --profile production
eas build --platform ios --profile preview
eas build --platform ios --local
# Submit
eas submit --platform ios --latest
eas submit --platform ios --id <build-id>
# Updates
eas update --branch production --message "Fix"
eas update:list
# Credentials
eas credentials --platform ios
eas credentials:configure
# View builds
eas build:list
eas build:view <build-id>
eas build:cancel <build-id>
# Secrets
eas secret:create --name KEY --value "xxx"
eas secret:list