React Native and Expo apps are shared like any other iOS app: as a signed .ipa. Here's how to get one and send it.
Get an .ipa
React Native CLI: open ios/YourApp.xcworkspace in Xcode, archive the app, and export it with Release Testing. Step-by-step export guide.
Expo (EAS Build): set "distribution": "internal" on a build profile in eas.json, then run:
eas build --platform ios --profile preview
EAS gives you a download link for the .ipa when the build finishes. To send every build straight to testers, build locally or on your own CI and upload in the same script:
eas build --platform ios --profile preview --local --output build/app.ipa npx buildferry upload build/app.ipa
Set BUILDFERRY_TOKEN to a token from Upload from CI in the BuildFerry dashboard.
Share it
EAS internal distribution can register devices with eas device:create, but a new device needs a new build before it can install.
With BuildFerry, upload the same .ipa and share one link. When a tester asks, you approve their iPhone, and BuildFerry registers it and re-signs the build in the cloud, with no new EAS build and no Mac.
Over-the-air updates
If you use EAS Update or another over-the-air JavaScript update service, testers keep receiving JavaScript changes in the installed build. You only need a new .ipa when native code or configuration changes.
Tips
- Release builds only. Debug builds expect the Metro bundler on your Mac.
- Keep one bundle ID per environment, such as
com.example.app.staging, so a staging build doesn't replace the production app on a tester's iPhone.
Questions
How do I install an Expo build on iPhone without TestFlight?
Build with an internal distribution profile in EAS, download the .ipa, and share it. BuildFerry registers each new iPhone and re-signs the .ipa, so you don't rebuild for each tester.
Can I share a React Native debug build?
Not usefully. Debug builds load JavaScript from Metro on your computer. Share a release build instead.