Wireless deploy to iPhone¶
This app uses a custom dev client (native modules: audio, video, reanimated), so it does not run in Expo Go. You install the dev client on the phone once, then iterate over Wi-Fi with no rebuilds for JavaScript changes.
The short version is
pnpm launch wifi. It runs the preflight checks and starts both servers. This page is the detail behind it: signing, iPad, and TestFlight account problems. For the other launch modes (simulator, Accessibility Inspector, Android, TestFlight) and the full Wi-Fi troubleshooting table, see Launching the app.Run these from the repo root.
deploy:iphone,ios:device, anddev:backend:lanare root scripts, because they span the backend and the app. Running one fromapps/mobile/fails withERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL: Command "deploy:iphone" not found. From a subdirectory, usepnpm -w <script>instead.
Prerequisites (once)¶
Building to a physical device also needs an Apple Team set for signing. If the
first build prompts for it, open apps/mobile/ios/SeniorHealthApp.xcworkspace in
Xcode, select the SeniorHealthApp target, and set your Team under
Signing & Capabilities.
One-time: install the dev client on the iPhone¶
- Connect the iPhone by USB, unlock it, and tap Trust if prompted.
- Build and install the native dev client:
Select your iPhone when prompted. The first build takes several minutes
(ios/ and Pods/ are already generated, so it is a warm build).
- Optional, recommended: enable wireless installs for the future. In Xcode open Window → Devices and Simulators, select your iPhone, and check Connect via network. After this you can rebuild without the cable.
Everyday wireless flow¶
- Put the Mac and iPhone on the same Wi-Fi network.
- Start everything with one command:
This prints your Mac's LAN IP, then starts the backend on 0.0.0.0:8000
(reachable by the phone) and the Expo dev-client Metro server bound to the
LAN, with a QR code.
- Open the installed Senior Health App dev client on the phone. It connects to Metro automatically; scan the QR if it does not. The app derives the backend address from the Metro URL, so no manual configuration is needed.
- Edit and save a file. The change hot reloads over Wi-Fi. No rebuild.
Stop the servers with Ctrl+C.
When to rebuild natively¶
Run pnpm ios:device again only when the native layer changes: adding or
updating a native module, changing app.config.ts plugins or permissions, or
updating app icons and splash. Pure JavaScript, TypeScript, and asset changes
never need a rebuild; they hot reload.
Related scripts¶
All of these live in the root package.json, so run them from the repo root
(or prefix with pnpm -w from anywhere).
| Command | What it does |
|---|---|
pnpm launch wifi |
deploy:iphone with the preflight checks in front of it |
pnpm deploy:iphone |
Backend (0.0.0.0) + LAN dev-client Metro, prints IP |
pnpm ios:device |
One-time native build and install to a connected iPhone |
pnpm dev:backend:lan |
Backend only, bound to 0.0.0.0 so the phone can reach it |
If the phone will not connect, work through the troubleshooting table in Launching the app. The usual causes are the macOS firewall, a VPN on the Mac, or a guest Wi-Fi network that isolates clients from each other.
TestFlight, including iPad¶
Ship a build to TestFlight from apps/mobile/ (running EAS from the repo root
fails during the Bundle JavaScript phase):
cd apps/mobile
eas build --profile production --platform ios # auto-submits are off; then:
eas submit --platform ios --latest # assigns the "Tester" group
Every build is universal. app.config.ts sets supportsTablet: true (with
requireFullScreen: true, so the iPad shows the phone layout full screen), and
the generated project carries TARGETED_DEVICE_FAMILY = "1,2". There is no
iPhone-only build to fix; an iPad on iPadOS 16.4 or later can always install
the current build.
"This app isn't available for your Apple Account" on iPad¶
That message is about the account, not the device. A TestFlight invite binds to the Apple Account that redeems it, not to the email address it was sent to, so a build that installs fine on the iPhone can still be "not available" on an iPad signed into a different account. In order:
- On the iPad, open TestFlight and tap the account avatar. It must show the same Apple Account that accepted the tester invite. If it does not, either sign that account in, or add the iPad's account as a tester in App Store Connect (group "Tester") and open the new invite on the iPad.
- Accept the invite on the iPad itself: open the invite email's View in TestFlight link there, or enter the redeem code in the TestFlight app.
- Builds expire after 90 days. If the newest build has expired, push a fresh
one with the two commands above;
eas.jsonassigns the "Tester" group on submit, so testers see it without any App Store Connect clicking. - Check the iPad runs iPadOS 16.4 or later, the minimum for this app. Older iPads cannot install it and nothing in the project can lower that floor.