Appearance
iOS readiness
What exists, what does not, and what actually blocks an iOS release of Snag.
Snapshot dated 2026-08-04, taken against poc-tcg-collector@main.
TL;DR
- There is no iOS project. Not an incomplete one —
ios/does not exist in the repository at all. - The blocker people expect, "we need a Mac", is already solved and costs nothing: Codemagic builds on macOS in the cloud. Expo's EAS Build solves the same problem the same way.
- The blockers that are real are an Apple Developer licence (€99/year, no way around it) and the fact that the iOS Simulator has no camera — so the scan, this product's ranked-first differentiator, cannot be tested anywhere but a physical iPhone.
- Nothing here can be validated from Windows or from the VPS. The first Codemagic run is the first honest signal.
Where the project actually stands
CLAUDE.md in the mobile repository states that "nothing under ios/ has ever been compiled here". The stronger fact is that there is nothing to compile:
git ls-files | grep "^ios/" → 0 files
Podfile, .xcodeproj, .xcworkspace → none anywhere in the tree
npm run ios → "react-native run-ios" … against nothingThe npm script survives from the React Native template. It has never had a target.
There is also, deliberately, almost no platform branching in the app: a single Platform.OS site in the whole src tree (src/scan/backendConfig.ts). The JavaScript is not the problem. The native shell is.
What Android has and iOS does not
| Concern | Android today | iOS requires |
|---|---|---|
| Native project | android/, AGP 7.4.2, compileSdk 34 | generate from the React Native 0.73.6 template |
| Native dependencies | resolved by Gradle | six pods wired through CocoaPods |
| Fonts | 5 .ttf under android/app/src/main/assets/fonts | copy into the Xcode project and declare UIAppFonts in Info.plist |
| Permissions | INTERNET, CAMERA in the manifest | NSCameraUsageDescription, NSPhotoLibraryUsageDescription — user-facing French copy, not placeholders |
| Identity | com.poctcgcollector | bundle identifier, app icons, launch screen |
| Display name | "TCG Collector" | a decision: the product is Snag, the repository name is historical |
The six native dependencies to integrate:
react-native-vision-camera
@react-native-ml-kit/text-recognition
react-native-image-picker
react-native-svg
react-native-safe-area-context
@react-native-async-storage/async-storageFive of those are routine on iOS. @react-native-ml-kit/text-recognition is the one to verify before committing to a plan — ML Kit on iOS carries its own binary-size and pod-configuration constraints, and its Expo support is unconfirmed. Verify it; do not assume it.
A gap already in the code
src/scan/resolveBackendHost.ts decides which host the scanner calls:
ts
if (input.platformOS !== 'android') return false;The emulator shortcut — http://10.0.2.2, the host loopback — is Android-only. An iOS Simulator therefore falls through to SHARED_BACKEND_HOST, the Tailscale Funnel address.
Two consequences. First, the very first iOS run would fail on the network rather than on the build, which is a confusing way to start. Second, an iOS Simulator runs on the developer machine, so http://localhost is the correct local target there — the equivalent shortcut exists, it simply has never been written.
This is a small change and it belongs in the same ticket as generating ios/, because a green build that cannot reach the backend proves very little.
The three blockers, ranked by hardness
1. iOS cannot be compiled without macOS — already solved
Neither the Windows workstation nor the Linux VPS can produce an iOS build, whatever code is written. This is not a matter of effort.
It is also already handled: the V2 pipeline in the CTO playbook puts iOS builds on Codemagic, which runs macOS workers. That is why Codemagic is in the plan; it is the only path, not a convenience.
2. Apple Developer licence — €99/year, unavoidable
No signing, no provisioning profile, no TestFlight, no App Store. This holds no matter which build tool is used, because it is Apple's requirement rather than the toolchain's. It cannot be worked around, and account approval is not instant — start it before it is on the critical path.
3. The Simulator has no camera — changes the test plan
On Android the scan is validated for free on an emulator. On iOS it cannot be validated on a simulator at all, because there is no camera device to open.
Since the product's stated first differentiator is a scan faster than the competition's, this is not a detail. Validating iOS scan behaviour requires a physical iPhone plus a distribution channel — TestFlight or Firebase App Distribution. Budget for the device and the distribution setup, not just the build minutes.
Does Expo remove the need for a Mac?
Yes — and it is the wrong reason to adopt it.
What Expo solves. EAS Build compiles on Expo's macOS machines; a build is triggered from Windows and an .ipa comes back. But Codemagic already does exactly this, and Codemagic is already the plan. "No Mac" is not an Expo advantage here; it is a property both tools share.
What Expo does not solve. The Apple Developer licence is still required. The Simulator still has no camera. Neither blocker moves.
What Expo genuinely offers. expo prebuild generates ios/ and android/ from app.json plus config plugins, instead of them being checked-in directories maintained by hand. That removes exactly the work listed in the table above — Podfile, Info.plist, fonts, permissions become declarative configuration. And the versions line up: Expo SDK 50 ships React Native 0.73, which is what this app runs, so a migration would not be compounded by a framework upgrade.
What it costs.
- Expo Go will never run this app.
vision-cameraand ML Kit are native code, so development builds are required, which means going through EAS for every native change. The "instant testing on a phone" argument does not apply to this product. vision-cameraships an official config plugin;image-pickerand the rest are unremarkable. ML Kit text recognition is the unknown. If a maintained plugin does not exist and one has to be written, the migration's saving evaporates.
Recommendation: do not migrate to Expo to reach iOS. The Mac problem is already solved, the Android project works and is understood, and the migration would cost days for a benefit that reduces to "ios/ is generated rather than written". Adopting Expo is a defensible architecture decision to make deliberately — it is not a shortcut around buying hardware that does not need buying.
Recommended order
Ordered to spend the least money before the first real signal.
- Open the Apple Developer account. It gates everything and approval takes days. Start it even in a week where no iOS code is written.
- Generate
ios/and commit it. Free, doable from Windows, and Codemagic needs the directory to exist before it has anything to build. Wire the Podfile, fonts, permissions, bundle identifier — and fix theresolveBackendHostgap in the same change. - Point Codemagic at an iOS workflow. The first run reports what is actually missing. That list cannot be produced by reading code from a non-Mac machine, so do not try to pre-empt it.
- A physical iPhone plus Firebase App Distribution, for the scan path.
Honest limits of this document
Step 2 produces a plausible iOS project that nobody has compiled. It is preparation, not validation. Expect the first Codemagic run to invalidate part of it; that is the run's job.
Anything in here about ML Kit on iOS is flagged as unverified on purpose. It is the one dependency likely to produce a surprise, and a surprise named in advance is cheaper than one discovered mid-migration.
See also
- CTO playbook — the V2 pipeline, where Codemagic and the release gates are defined
- Architecture overview — the whole stack, and where the mobile client sits in it