Part of #79.
Problem
Everything verified so far is a Simulator build (CODE_SIGNING_ALLOWED=NO). Nothing has run on a physical iPhone, and the Simulator hides the things that only matter on device: code signing, the entitlements actually taking effect, universal links, real WebView performance over a cellular connection, and safe-area/notch layout on a real screen.
There is also a hard constraint worth writing down: a phone cannot reach this Mac's localhost. A device build has to point at a real https origin — benchreview.org (see the deploy issue) or a tunnel — or be built fully bundled with MOBILE_E2E=1. config/mobile.ts already reads MOBILE_URL for this.
What to do
Port scripts/run-ios-device.ts from wildloop (276 lines): it creates a Release device build, signs it, installs on the single connected iPhone and launches. Its flags are the useful part:
preview:iphone Release, signed, loads the production origin
preview:iphone --personal-team free Apple team: drops Associated Domains + Push
preview:iphone --bundled the exact local frontend, for offline testing
preview:iphone --server=https://… a tunnel or staging origin
check:iphone compile only, no install--personal-team matters: a free team cannot sign Associated Domains or Push Notifications and Xcode refuses the whole profile rather than dropping just those, which is why config/mobile.ts already empties associatedDomains when IOS_PERSONAL_TEAM=1.
Prerequisites
APPLE_TEAM_IDin the environment —config/mobile.tsreads it and currently resolves toundefined, which is fine for Simulator and not for device- A registered device on the team, or the personal-team path
Checks
bun run check:iphonecompiles a Release build unsignedpreview:iphoneinstalls and launches on a connected device- Safe-area layout checked on a notched device — the site was designed for desktop-first breakpoints
- Portrait lock behaves (
orientations: ['portrait']) --bundledbuild works with no network at all (airplane mode)