App Store / Play Store
Publishing a React Native app to the App Store and Play Store. The pipeline: bump versions, build a signed binary, upload via EAS Submit (or fastlane), fill in store listings, attach screenshots, and submit. After review, deploy JS-only updates via EAS Update without rebuilding.
EAS Submit, store listings, screenshots, rollouts
EXAMPLE
# ===== Prereqs =====
# - Apple Developer account + App Store Connect access
# - Google Play Console account
# - EAS CLI: npm i -g eas-cli
# - Logged in: eas login
# - Configured: eas init (creates eas.json)
# ===== 1) eas.json — the build matrix =====
{
"cli": { "version": ">= 10.0.0" },
"build": {
"development": { "developmentClient": true, "distribution": "internal" },
"preview": { "distribution": "internal", "ios": { "simulator": true } },
"production": { "autoIncrement": true, "env": { "API_BASE": "https://api.example.com" } }
},
"submit": {
"production": {
"ios": { "ascAppId": "6471234567", "appleId": "you@example.com", "ascApiKeyPath": "./asc-api.json" },
"android": { "track": "internal", "serviceAccountKeyPath": "./play-service-account.json" }
}
}
}
# ===== 2) Bump version + build =====
# app.json / app.config.ts
# {
# expo: {
# version: '1.4.0',
# ios: { buildNumber: '142' },
# android: { versionCode: 142 },
# runtimeVersion: { policy: 'appVersion' },
# updates: { url: 'https://u.expo.dev/<project-id>' }
# }
# }
eas build --platform all --profile production
# Output: signed .ipa + .aab on EAS infrastructure. Download URLs to test
# from a real device before submitting.
# ===== 3) Submit =====
eas submit --platform ios --latest --profile production
eas submit --platform android --latest --profile production
# Manual alternative: download artefacts from EAS, upload via:
# - iOS: Transporter app or 'xcrun altool --upload-app'
# - Android: Google Play Console -> Internal testing -> Create release
# ===== 4) App Store Connect — checklist =====
# - App information: subtitle (30 char), keywords (100 char), support URL
# - Pricing + availability
# - App privacy: data types collected, link to privacy policy
# - Age rating questionnaire
# - Build selection (choose the EAS-uploaded one)
# - What's new in this version
# - Promotional text (up to 170 char, changeable without re-review)
# - Screenshots:
# 6.7" / 6.5" iPhone (mandatory)
# 13" iPad if you support iPad
# 1290x2796 / 1242x2688 / 2064x2752
# - App Preview videos (optional but helpful)
# - Demo account credentials (required if gated content)
# ===== 5) Google Play Console — checklist =====
# - App access (any login-gated features need a test account)
# - Ads declaration
# - Content rating questionnaire (IARC)
# - Target audience + content
# - News app? Government app? Health app? Disclose accordingly
# - Data safety form (analogous to App Privacy on iOS)
# - Store listing: short description (80), full description (4000)
# - Graphic assets: icon 512x512, feature graphic 1024x500
# - Screenshots: phone (1080p), 7" tablet, 10" tablet
# - Promo video (YouTube URL)
# - Countries to release in
# ===== 6) Staged rollout =====
# Play Console -> Production -> 5% -> 25% -> 50% -> 100% over a week.
# Stop if crash rate ticks up or rating drops.
#
# App Store Connect -> Phased Release for Automatic Updates (7-day curve).
# ===== 7) Once approved: ship JS-only updates via EAS Update =====
eas update --branch production --message 'Fix checkout copy'
# Devices fetch on next launch. Stay within the runtimeVersion bound or the
# bundle is rejected.
# ===== 8) After-launch ops =====
# - Crashlytics + Sentry alerts wired to Slack
# - Reviews monitor: tools like AppFollow / a daily cron emailing top 1-stars
# - Subscription metrics (RevenueCat / Adapty) if you sell IAPs
# - Watch retention curves; rage uninstalls show up in 'Last 7 days' Play data
# ===== 9) Common rejections + fixes =====
# - 'Missing demo account' (iOS) -> provide one in App Review notes
# - 'Privacy policy URL required' -> add to App Store + Play Console
# - 'Background mode misuse' (iOS) -> remove unused entitlement
# - 'Target API level too old' (Play) -> bump targetSdkVersion
# - 'Crash on launch on review device' -> test on a CLEAN device before submission
# - 'Misleading IAP descriptions' -> match the in-app copy exactly
# - 'Permissions justification' (Play) -> short reason for each permission
# ===== 10) Pitfalls =====
# - Submitting on a Friday — review queues are longer over weekends
# - Skipping staged rollout — a regression hits everyone at once
# - OTA pushing JS that calls native APIs the binary does not have
# (mismatched runtimeVersion = crash storm)
# - Forgetting to keep the signing keystore safe — losing it bricks future updates
# - Not having a rollback plan — keep the previous build .aab to revert quickly
Why it matters
Always do a staged rollout on Play (5% → 25% → 100%) and use Phased Release on App Store. If Crashlytics ticks up at 5%, you pause; if it stays flat, you continue. The cost is one or two weeks of slower distribution; the benefit is never "we shipped to 100M users on Tuesday and 30% had a crash on launch".
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Build and submit eas build -p ios --profile production eas submit -p ios --latest eas build -p android --profile production eas submit -p android --latestTry it Yourself »
Discussion
Loading…