You’ve built your React Native app. Now comes the part everyone underestimates: getting it into both stores without hitting a wall of rejected submissions, outdated signing instructions, or privacy policy flags.

This chapter of React Native Unplugged covers the full publishing process for 2026 — including updated Android SDK requirements, iOS Privacy Manifests, and a dedicated section for Expo projects using EAS Build. Let’s ship.

React Native logo for a series on solutions, performance tips, and best practices.

Before You Build: Prepare Your App for Production

A few things to handle before you touch any build commands:

  • Remove all console.log statements or gate them behind a __DEV__ check.
  • Set your app version and build number — both stores track these separately, and you can’t reuse a build number once submitted.
  • Test on real devices, not just simulators. Crashes that only appear on physical hardware are the most embarrassing kind to discover post-launch.
  • Have your privacy policy URL ready. Both Google and Apple require one, and submission will fail without it.

Publishing to Google Play (Android)

Step 1: Generate a Keystore

Your keystore is what signs your app and ties it permanently to your developer account. Generate it once and back it up — losing it means you can never update your existing app.

keytool -genkeypair -v -keystore my-release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias my-key-alias

Save my-release-key.jks in android/app/. Add it to .gitignore — never commit your keystore to version control.

Step 2: Configure Signing in Gradle

Edit android/gradle.properties:

MYAPP_RELEASE_STORE_FILE=my-release-key.jks
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=your-password
MYAPP_RELEASE_KEY_PASSWORD=your-password

Then update android/app/build.gradle:

android {
  signingConfigs {
    release {
      storeFile file(MYAPP_RELEASE_STORE_FILE)
      storePassword MYAPP_RELEASE_STORE_PASSWORD
      keyAlias MYAPP_RELEASE_KEY_ALIAS
      keyPassword MYAPP_RELEASE_KEY_PASSWORD
    }
  }
  buildTypes {
    release {
      signingConfig signingConfigs.release
      minifyEnabled true
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
}

Step 3: Set Your Target SDK

Google Play currently requires new apps and updates to target Android 15 (API 35) at minimum. Starting August 31, 2026, that floor rises to Android 16 (API 36). Check your build.gradle:

android {
  compileSdkVersion 36
  defaultConfig {
    targetSdkVersion 35   // required now; use 36 before Aug 31, 2026
    minSdkVersion 24
  }
}

If your targetSdkVersion is below the current Play requirement, your update will be rejected during review.

Step 4: Build an Android App Bundle (AAB)

Google Play requires AAB format for all new apps and updates — APK uploads are no longer accepted for new submissions.

cd android
./gradlew bundleRelease

Find the output at android/app/build/outputs/bundle/release/app-release.aab.

Step 5: Upload to Google Play Console

  1. Go to Google Play Console and create your app.
  2. Complete the Data Safety section — this is mandatory and requires you to declare what data your app collects and why.
  3. Upload your .aab under Production → Releases.
  4. Fill out your store listing: screenshots (required sizes vary by device type), short description, full description, and a privacy policy URL.
  5. Submit for review. First-time reviews typically take 3–7 days.

Publishing to the App Store (iOS)

Step 1: Apple Developer Program

Sign up at developer.apple.com. Publishing to the App Store requires enrollment in the Apple Developer Program ($99/year). The free tier only allows device testing.

Step 2: Add a Privacy Manifest

Since May 2024, Apple requires a Privacy Manifest file for all app submissions. Without it, your build will be rejected.

Create ios/PrivacyInfo.xcprivacy and add it to your Xcode project:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>NSPrivacyTracking</key>
  <false/>
  <key>NSPrivacyCollectedDataTypes</key>
  <array/>
  <key>NSPrivacyAccessedAPITypes</key>
  <array/>
</dict>
</plist>

Adjust the values based on the data your app actually accesses. An empty manifest is only safe if you truly collect nothing and call none of Apple’s “required reason APIs.” If you use UserDefaults, file timestamps, disk space APIs, or similar, you must declare the reason codes in NSPrivacyAccessedAPITypes — or Apple will reject the build.

Step 3: Configure Xcode for Production

Open ios/AppName.xcworkspace in the latest Xcode.

  • Set your Bundle Identifier under Signing & Capabilities.
  • Select your Team (your Apple Developer account).
  • Set Deployment Target — iOS 16+ is a practical floor for most new apps.
  • Install pods if you haven’t: cd ios && pod install.

Step 4: Archive and Upload

run-ios in Release mode only launches the app — it does not create a store build. To ship, archive from Xcode:

  1. Select Any iOS Device (arm64) as the run destination (not a simulator).
  2. Go to Product → Archive.
  3. In the Organizer, choose Distribute App → App Store Connect.

You can also use Transporter (free Mac app) to upload a .ipa manually, or skip Xcode entirely with EAS Build (covered below).

Step 5: Configure App Store Connect

  1. Go to App Store Connect and create your app record.
  2. Fill out your App Store listing: screenshots for each device size, description, keywords, and support URL.
  3. Complete Privacy Nutrition Labels — declare what data your app collects and how it’s used.
  4. Use TestFlight for beta distribution before going live.
  5. Submit for review. Average review time is 24–48 hours, though first submissions may take longer.

Publishing with Expo (EAS Build)

If your project uses Expo, you can skip the manual Xcode and Gradle build steps above. EAS Build (Expo Application Services) handles signing, building, and binary upload from the command line — store listing and review still happen in each console.

Setup

npm install -g eas-cli
eas login
eas build:configure

This generates an eas.json file with your build profiles.

Build for Both Platforms

# Android
eas build --platform android --profile production

# iOS
eas build --platform ios --profile production

# Or both at once
eas build --platform all --profile production

EAS handles keystore generation and certificate management automatically on the first run — or you can supply your own.

Submit Directly to the Stores

eas submit --platform android
eas submit --platform ios

eas submit uploads your build to Google Play Console or App Store Connect — no Transporter, no manual binary upload. It does not finish the store listing or start production review for you. On Android, the first submit often lands on the internal testing track; on iOS, the build shows up in App Store Connect (and TestFlight). You still complete Data Safety / Privacy Labels, screenshots, and hit Submit for Review in each console.

EAS also skips the manual Gradle and Xcode build steps, but not the compliance work: Privacy Manifests, privacy policy URLs, and store questionnaires still apply.

For teams running CI/CD, EAS integrates with GitHub Actions and other pipelines, so builds and submissions can trigger automatically on merge to main.

Pre-Submission Checklist

  • App version and build number updated
  • All console.log statements removed or gated
  • Tested on real Android and iOS devices
  • Privacy policy URL live and accessible
  • Google Play: Data Safety section completed
  • Google Play: targetSdkVersion set to 35 or higher (36 before August 31, 2026)
  • App Store: Privacy Manifest (PrivacyInfo.xcprivacy) added and filled in for any required reason APIs you use
  • App Store: Privacy Nutrition Labels completed in App Store Connect
  • Screenshots prepared for all required device sizes
  • Crash reporting configured (Firebase Crashlytics or equivalent)

What’s Next

Your app is live. The work that actually determines whether it succeeds is what comes after: monitoring crashes, keeping performance tight, and iterating on what users do inside the product.

If your release starts feeling slow under real traffic, go back to React Native performance optimization. If multi-screen flows still feel fragile, navigation best practices is the chapter to revisit. Publishing gets you into the stores — the rest of React Native Unplugged is what helps you stay there.