Quick answer
To share a live mobile preview without TestFlight, install an internal distribution build on each tester's device once: an ad hoc signed build for registered iPhones, or an APK for Android. After that, send each JavaScript change as an over-the-air update the installed build can load, and rebuild only when native code changes. A hosted simulator in the browser covers reviewers without a registered device.
Why share a preview without TestFlight?
4:52 p.m. The designer wants to try the new onboarding flow on her own iPhone before tomorrow's 9 a.m. review. You uploaded the build to App Store Connect an hour ago, and it still isn't available to testers.
TestFlight is built for beta programs, and its process shows. A build has to be uploaded to App Store Connect and pass an automated review before anyone can install it. Internal testers must be members of your App Store Connect team, up to 100 people. According to Apple's TestFlight page, you can invite up to 10,000 external testers, but your first build for them needs App Review approval. Store testing tracks also accept only release builds, so a development build with debugging tools cannot go through them.
For a preview you will replace three times before lunch, a path that skips the upload is quicker to repeat. TestFlight is still the better choice for a large beta group, for testers whose devices you cannot register, and for rehearsing the store release itself.
Step 1: Decide whether the reviewer needs a phone or a browser
Start with what the reviewer has to check. Button placement and copy can be judged in a browser. Camera capture, push notifications and how the app feels in the hand need a real phone.
A live browser session means the app runs on a remote simulator and its screen is streamed to the reviewer. No iPhone binary runs inside the browser. An installable build runs on the reviewer's own device and follows that platform's installation rules.
| Path | Best fit | What the reviewer needs | What it cannot show |
|---|---|---|---|
| Hosted simulator session | Reviewing interaction and copy | A supported browser and access to the service | Real-phone hardware behavior |
| iOS ad hoc build | Trying a native build on known test iPhones | A device registered before the build was signed | Installation on unregistered iPhones |
| Android APK | Trying the app on a test Android phone | Permission to install apps from outside Google Play | Google Play release behavior |
| Development or preview build plus updates | Repeated review by testers who already have the app installed | A compatible build installed and a network connection | Changes that need different native code |
| Web preview | Reviewing a web version of the app | A browser | Native-app parity |
Tell the reviewer which one you are sending. A surprise install step can stall the review for a day.
Step 2: Register iPhones and build for internal distribution
Ad hoc provisioning is Apple's way to install a signed build on specific test devices without App Store Connect. The provisioning profile holds an allow-list of device UDIDs, and only devices on that list when the build was signed can install it. A new tester means registering their device and building or re-signing again, so collect UDIDs before the review, not during it.
Apple caps ad hoc distribution at 100 iPhones per year on a paid Apple Developer account, and disabled devices still count against the limit. On a new or recently renewed membership, Apple can take 24 to 72 hours to process a newly registered device, and a build that includes it may fail until then.
Android is simpler. An APK installs directly from a download link, email or chat once the tester accepts the warning for apps that have not gone through Play Store review. An AAB is a publishing format for Google Play and cannot be installed by tapping a file.
Enterprise distribution through the Apple Developer Enterprise Program has no device list, but it is only for apps used by an organization's own employees. Don't use it as a public-testing workaround.
Services such as Firebase App Distribution deliver APK, AAB or IPA files to invited testers. Apple's device list still applies to an ad hoc IPA, whichever service sends it.
Step 3: Send JavaScript changes as updates to the installed build
Rebuilding and reinstalling for every copy change wastes the reviewer's time. Once a tester has a development build or preview build installed, an over-the-air update can deliver new JavaScript and assets to it, and the next preview reaches them without a new install.
An update only works on a build with compatible native code. If your change adds a native module or changes native configuration, sending new JavaScript to an older build will not add the missing capability, and you need a new build.
Keep the preview revision visible in the app or the link. If you publish a new update while someone is reviewing, their feedback can describe a version you no longer have on screen.
Step 4: Send the link with a short review task
A preview should arrive with enough context for the reviewer to use it without a call. Describe the starting state and the flow to try, say what changed and what is out of scope, and keep it short enough to follow with the app open:
Open the link with the reviewer's access level before you send it. A URL that works only because you are signed in as the project owner is not a working handoff.
Attach every piece of feedback to the build or update it came from. A screenshot with no build ID is hard to act on once the next change lands.
Step 5: Control who can open the preview, and clean up
Know who can open the link and what it lets them do. A hard-to-guess URL is not the same as authenticated access.
Use dedicated test accounts and data, never a real customer's account. A preview that can create real bookings or send customer notifications needs an isolated backend and a reset path. Check whether recordings or logs from a hosted session are visible to the same audience, since they can contain test-account details.
Keep the preview available for the agreed review window, and send a new link when the build changes.
Why won't the preview open?
"The preview is broken" can mean several different failures. Find the last step that worked before you change the build.
| Symptom | First check | What to ask for |
|---|---|---|
| Reviewer cannot open the link | Link validity and the reviewer's real access | The access message, and whether they are signed in |
| iPhone refuses to install the build | Whether the device UDID was in the profile when the build was signed | The exact installation message and device model |
| Session opens but the app never appears | Simulator build versus device build, and the launch result | The session ID and launch log |
| App opens but sign-in fails | Test-account state and the backend or redirect configuration | The failed step and sanitized logs |
| Update does not appear | Whether the installed build's native code is compatible with the update | The build and update IDs shown in the app |
| Feedback describes an older screen | Which build or update the reviewer had open | The build or update ID shown during the review |
Keep app failures apart from delivery failures. If the app launches and then crashes in the booking flow, a new link won't fix it. If the preview works only on your machine, remember that a remote simulator does not share your laptop's local network, and point it at a reachable test server instead of exposing a private one.
Close the review with the result and any untested gap. "Booking copy approved in the hosted iOS Simulator; physical-device calendar access still untested" tells the release owner far more than "preview approved."
Where Expo fits
EAS Build handles the signing for internal distribution. Setting "distribution": "internal" on a profile in eas.json makes Android builds produce an APK instead of an AAB and makes iOS builds use ad hoc or enterprise provisioning. A separate profile with ios.simulator set to true produces a build for the iOS Simulator:
Register a tester's iPhone with eas device:create, then build with the profile for the destination:
The first command creates an iOS Simulator build and the second an Android APK for internal distribution; neither starts a hosted session by itself. The simulator build guide covers the setup. Each internal distribution build gets an install URL that anyone with the link can open by default, and you can require an Expo sign-in by turning off unauthenticated access in your project settings.
EAS Update covers Step 3. After a tester installs a development build through internal distribution, they can open any compatible update you publish. Running eas update --auto publishes one under your current Git branch name and prints a dashboard link; the reviewer opens it, selects Preview and scans the QR code. The preview guide also shows an EAS Workflows file that publishes a preview update on every push:
Expo Go has a fixed set of native libraries, and Expo's review overview says it is not meant for reviewing your app. An app with its own native code needs a development build.
Expo Simulators is in early access with a waitlist. Confirm your account's access and the current sharing flow before you promise a reviewer a link.
Limitations
A browser-hosted simulator does not replace checks on a physical phone. Access and sharing behavior can differ between services and accounts, so test the exact reviewer flow instead of assuming anonymous links or support for every native library. Ad hoc builds stay limited by Apple's device list and the 100-device yearly cap. For a wide beta program or a rehearsal of store distribution, TestFlight or a Google Play testing track is still the right tool.
Next step
Use the internal distribution guide to build one preview for a registered device, then test the full handoff from the reviewer's access level.
Verified on 12 September 2026.
