Submit an Expo/React Native app to the iOS App Store. Covers Apple Developer account, certificates, provisioning profiles, EAS Build and Submit, TestFlight, build versioning, and common rejection reasons. Use when the user wants to publish to the App Store.
Use this skill when the user:
com.example.myapp (set in app.json)Configure app.json for production.
{
"expo": {
"name": "My App",
"slug": "my-app",
"version": "1.0.0",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"bundleIdentifier": "com.example.myapp",
"buildNumber": "1",
"supportsTablet": false,
"infoPlist": {
"NSCameraUsageDescription": "This app uses the camera to...",
"NSPhotoLibraryUsageDescription": "This app accesses photos to..."
}
}
}
}
Every NS*UsageDescription string must clearly explain why the app needs that permission. Vague reasons cause rejections.
Set up EAS Build. Install and configure:
npm install -g eas-cli
eas login
eas build:configure
This creates eas.json with build profiles:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
}
}
Set "autoIncrement": true on the production profile to auto-bump buildNumber.
Certificates and provisioning profiles. EAS handles this automatically:
eas build --platform ios --profile production
On first run, EAS will:
To manage credentials manually:
eas credentials
To use your own certificates, configure in eas.json:
{
"build": {
"production": {
"ios": {
"credentialsSource": "local"
}
}
}
}
Build for the App Store.
eas build --platform ios --profile production
This produces an .ipa file uploaded to Expo's servers. The build typically takes 15-30 minutes.
Monitor at: https://expo.dev/accounts/<username>/projects/<slug>/builds
Submit to App Store Connect.
eas submit --platform ios
EAS Submit will:
For automated submissions, create an App Store Connect API key:
eas submit --platform ios \
--asc-app-id 1234567890 \
--apple-id [email protected]
Or configure in eas.json:
{
"submit": {
"production": {
"ios": {
"appleId": "[email protected]",
"ascAppId": "1234567890",
"appleTeamId": "ABCDE12345"
}
}
}
}
TestFlight distribution. After upload, the build appears in App Store Connect under TestFlight:
Submit for App Review. In App Store Connect:
Review typically takes 24-48 hours. Expedited reviews are available for critical bug fixes.
SDK and Xcode requirements. Apple enforces minimum SDK versions:
| Deadline | Requirement |
|---|---|
| April 24, 2025 | iOS 18 SDK, Xcode 16 |
| April 28, 2026 | iOS 26 SDK, Xcode 26 |
Apps uploaded after the deadline must be built with the required Xcode version. Expo SDK 55+ with EAS Build handles this automatically.
AI disclosure. If the app uses AI features, Apple requires:
Add this information in the App Store Connect app description and in-app where AI features are used.
Age rating. Apple updated the age rating system in January 2026. Review and update responses in App Store Connect to avoid submission delays.
Common rejection reasons and fixes.
| Rejection | Fix |
|---|---|
| Guideline 2.1 - App crashes | Test on real devices; fix all crash paths |
| Guideline 2.3 - Inaccurate metadata | Screenshots must show current UI |
| Guideline 3.1.1 - In-App Purchase | Use IAP for digital content; no external payment links |
| Guideline 4.0 - Design minimum | Must provide meaningful functionality beyond a website wrapper |
| Guideline 5.1.1 - Data Collection | Disclose all data collected in privacy labels |
| Guideline 5.1.2 - Data Use | App Tracking Transparency required if using IDFA |
| Missing purpose string | Every permission must have a clear NS*UsageDescription |
User: "I want to submit my Expo app to the App Store for the first time."
Agent:
app.json has bundleIdentifier, version, buildNumber, icon, and splashmobile_validateStoreMetadata to check for missing fieldseas build --platform ios --profile productioneas submit --platform ios| Step | MCP Tool | Description |
|---|---|---|
| Validate config | mobile_validateStoreMetadata | Check app.json has all required iOS fields |
| Build | mobile_buildForStore | Trigger eas build --platform ios --profile production |
| Submit | mobile_submitToAppStore | Trigger eas submit --platform ios |
| Check build | mobile_checkBuildHealth | Verify project compiles before EAS build |
autoIncrement: true in eas.json.