React Native: from project setup to the App Store and Google Play
Writing the app is the part everyone plans for. Signing, test tracks, privacy forms and store review are where launches slip. This is the path I follow from an empty repo to both stores.
I've built React and React Native apps for more than seven years, and taken several of them through App Store and Google Play review. They include a mobile banking app for Moldova with MAIB and MPass integrations and RevenueCat subscriptions, and a dating app, both built as an employee or contractor for the companies that own them. At Syncra we're now building our own mobile app, iBeep. It is still in development and not in the stores yet.
The code is rarely what delays a launch. What delays it is everything around the code: signing, test tracks, privacy declarations, review, and the first update after release. Here is the path I follow, in order.
1. Start with Expo, and move to development builds early
For a new React Native app, Expo is the default I reach for. The React Native docs themselves recommend starting with a framework, and Expo is the one most teams use. It gives you a sane project layout, file-based routing, a large set of maintained native modules and a build service.
Two decisions matter early:
- Use development builds, not Expo Go, as soon as you add a native module Expo Go doesn't include. A development build is your own app with a dev menu, and it behaves like production where it counts.
- Let Expo generate the native projects. With prebuild, the
iosandandroidfolders are generated from your app config, and native changes go through config plugins. Upgrades become a config change instead of a merge conflict in an Xcode project.
Going fully bare is rarely needed. Custom native code still fits, as an Expo module or a local config plugin.
2. Structure the repo for more than one app
A mobile app is rarely alone. There is an API, an admin tool, often a landing page. When those live in one monorepo, they can share types, validation schemas and constants, and a change to an API contract shows up as a type error in the app instead of a crash in production.
iBeep is built this way: a Turborepo monorepo with the Expo app, the API and the landing page side by side. Keep the boundaries clear. Shared packages hold types and pure logic, never React Native code that the server would have to install.
3. Separate environments from day one
Set up three variants before you need them: development, preview and production. Give each its own bundle identifier and app name, so all three can sit on the same phone without overwriting each other. A dynamic app.config.ts that reads an APP_VARIANT variable is enough.
One rule to repeat to the whole team: anything in the app bundle is public. Variables prefixed with EXPO_PUBLIC_ are compiled into the JavaScript that ships to every phone. API secrets belong on your server, and the app talks to the server.
4. Get signing right once
Signing is where first-time launches lose days.
- iOS needs an Apple Developer Program membership, a distribution certificate and provisioning profiles. EAS can create and manage these for you, which I recommend unless you have a reason not to.
- Android has two keys. With Play App Signing, Google holds the key that signs what users install, and you keep an upload key. Back the upload key up. If you lose it, you can ask for a reset, but you lose time.
- Choose your bundle identifier and package name carefully. They are permanent. You can rename an app, but you can't change its identifier.
Versioning has two numbers on each platform: the version people see, and a build number that must go up with every upload. Let the build service increment the build number for you, so two people never upload the same one.
5. Put it on real phones early
Simulators hide the problems that matter: slow devices, real networks, notifications, deep links, permission prompts. Get builds onto real phones in the first weeks, not the last.
- TestFlight gets a build to your internal testers within minutes of processing.
- Google Play's internal testing track does the same on Android.
Plan for one Google Play rule in particular. A new personal developer account must run a closed test with at least 12 testers, opted in continuously for at least 14 days, before it can apply for production access. That is two weeks you can't compress at the end, so start it early, or publish under an organisation account, where the rule doesn't apply.
6. Fill in the forms that block launches
Both stores ask what your app collects and why, and both check it.
- Privacy declarations. Apple's App Privacy details and Google Play's Data safety form must match what the app and every SDK in it actually collect: analytics, crash reporting, ads, authentication. List your SDKs before you fill in either form.
- Account deletion. If people can create an account in your app, Apple requires that they can start deleting it from inside the app. Google Play requires an in-app path and a web link where deletion can be requested. Build this as a feature, not as a support email.
- Privacy manifests on iOS. Apple requires them for certain system APIs, and many SDKs use those APIs. Keeping SDKs current is usually enough.
- Social login. If you offer sign-in with a third-party service, Apple generally requires an equivalent privacy-focused option as well. In practice, that usually means Sign in with Apple.
- Payments. Digital goods and subscriptions used inside the app generally have to go through each store's in-app purchase system. The rules differ by region and have been changing, so check the current guidelines for the markets you launch in. A subscription service such as RevenueCat saves you from writing receipt validation for two stores yourself.
7. Prepare for review
Most rejections are avoidable: a crash on the reviewer's device, a login with no demo account, placeholder content, metadata that promises features the app doesn't have, or a privacy declaration that doesn't match the app.
Write review notes that explain anything non-obvious, include a working demo account, and leave a few days of buffer for the first submission. Later reviews are usually faster, but a first submission is where questions come up.
8. Plan the first update before the launch
You will need to ship a fix within days of launch. Know in advance how.
- JavaScript and asset changes can go out as over-the-air updates, with EAS Update for example, without a new store review. Tie each update to a runtime version, so JavaScript never reaches a native binary it wasn't built for. Use these for fixes and improvements. The stores expect the app people install to stay the app that was reviewed.
- Native changes, such as a new native module, a permission or an SDK upgrade, need a new store build.
- Roll out gradually. The App Store's phased release and Google Play's staged rollouts let you ship to a share of users first and stop if crash reports climb.
Keep up with platform requirements. Google Play raises its target API level requirement every year, and Expo releases new SDKs several times a year. Small, regular upgrades are far cheaper than one big upgrade every two years.
A short checklist before you submit
- Bundle identifier and package name final, three app variants working.
- Signing managed, upload key backed up.
- Real-device testing on both platforms, including a slow Android phone.
- Closed test running early if your Google Play account needs it.
- Privacy declarations matching every SDK, account deletion built in.
- Review notes and a demo account ready.
- Crash reporting live and an update path tested before day one.
How we work at Syncra
We take mobile apps from an empty repo to both stores and keep them running after launch: React Native and Expo, the backend behind them, and the store work above. iBeep, our own app, goes through the same path. When it reaches the stores, you'll find it on this site.