A working app in Expo Go deceives you. You see your components rendered on your phone, the state syncs, navigation feels native, images load — and you think you're done. Ship it, right? Every first-time builder hits the same unspoken wall: what shows up in Expo Go is not a real app in the App Store or Play Store. That last 10% — the actual mobile deploy — is where side projects go to die. Most templates punt entirely, or leave you to stitch together deploy guides full of missing steps and platform traps. The OTF Fitness kit ships the deploy scripts and configs up front, closing the build gap that kills most cross-platform ambition. One line. It shows up on your homescreen with your icon, your name, ready for TestFlight, ready for review. Here’s what you actually face, and why offloading that last mile matters more than any demo.
The real wall: local preview ≠ shipped app
Developers new to cross-platform React see Expo Go’s QR code as the finish line. Not even close. Running this command:
npx create-expo-app my-workout
cd my-workout
npx expo start
puts your app in a simulator (Expo Go) that can sidestep half the real deploy. Critical things work here that will break in production:
- No code signing (any JS bundle, no review)
- No native build (Expo Go is a generic host)
- No App Store assets — icon, splash, name, permissions
- No device install — can’t tap from the homescreen
- No Play Store / App Store distribution or review
You can ship a working build in minutes to yourself, but it’s a shadow — not a real, installable app. When you try to cross the line, every step turns manual. This is where “ships on Expo” templates stall.
EAS build: what actual deployment takes
The transformation from “runs in Expo Go” to “actual binary on your phone” isn’t automatic. Expo’s EAS (Expo Application Services) build system does the heavy lifting, but you need to speak the production language:
- An EAS account — no anonymous builds
- iOS and Android credentials — signing keys, provisioning profiles, App Store Connect API keys
- A manifest with all permissions claimed, store assets, platform-specific config
- Uploaded icons, splash screens, app.json fields (names, ids, categories)
- Push notifications config (Apple .p8, Firebase sender id)
- Store-ready assets (screenshots, review notes)
Running a real build:
npx eas build --platform ios
npx eas build --platform android
will fail if any config is missing or invalid. Now you’re copy-pasting stack traces into Google and yak-shaving Apple Developer docs.
Real apps face real CI friction:
- One device build per platform — no “universal bundle”
- Apple review on each TestFlight push, Play Console requirements
- Test builds expire, OTA updates are gated
- Secrets, env vars, and API keys leak without care
The signing gauntlet: why code signing crushes momentum
Code signing is not optional — every iOS app must be cryptographically signed by an Apple Developer account, with device provisioning, store team memberships, and revocable keys. Android is only one step better — you own the key and lose it once, you’re dead.
For iOS:
- Apple Developer account ($99/year)
- App ID in App Store Connect
- Provisioning profile per app
- Team and bundle id setup
- App-specific passwords, App Store Connect API keys
If any field is off (bundle id mismatch, expired profile, revoked certificate), your build fails with cryptic output — and you lose hours to the Mac-only esoteric world of “Xcode, but headless.”
Android asks for:
- Play Developer account ($25 one-time)
- Keystore setup
- Package id, signed AAB
- Play Console config (listing, screenshots)
- Play integrity (attestation), device listing
No guide gets these all right; many template repos don’t even mention the gap. A cross-platform shipping template is only real if it closes this with scripts, not hand-wavy TODOs.
TestFlight and the Play Console: why “build and sideload” isn’t the real review pipeline
Anyone can sideload a local IPA or APK, but for actual users — and to pass review — you need:
- TestFlight build submission
- Metadata: app privacy, age ratings, review notes, demo creds
- Beta tester invites
- App Review turnaround, failure cycles
- Play Store staged rollout, device targeting
Half the first deploys fail here. Stalled on “waiting for review”, “missing privacy manifest”, or “no reviewers can sign in.” Painful but real: production deploys blow up on invisible requirements.
Kits that only demo: the land of abandoned build guides
Most cross-platform templates show a pretty screen — maybe an Expo snack, maybe a raw repo you clone and expo start. Real-world deploys are left as an exercise. That reads as:
# TODO: setup signing
# TODO: add EAS config
# TODO: push to App Store Connect
Worse: many ship with placeholders that break at build:
- Dummy bundle IDs (
com.example.app) - Lorem ipsum assets that fail size and content checks
- No privacy manifest — flagged at upload
- Missing push keys, icons, required fields
New builders lose a week to docs, then abandon at the first provisioning error. The rest never see the App Store.
The OTF Fitness kit closes the deploy gap: the build is part of the kit
The OTF Fitness kit is blunt: if you can't build and ship a real app to your phone, it doesn't count. That's why the Fitness kit includes:
- Deploy scripts for iOS and Android, with wiring for EAS and native release builds
- Store-ready
app.jsonandeas.json, with all required fields pre-filled — icons, splash, permissions, bundle/package ids - Placeholder secrets/envs wired to expect override, not fail
- A one-line setup script for native signing:
pnpm otf-kit setup:mobile
# or for npm users
npx otf-kit setup:mobile
- Prebuilt store screenshot assets and review notes for TestFlight + Play Console (modular, swap your name and icon)
- Failsafe hooks: if an asset or required value is missing, the build script blocks, notifies, and tells you what to fix — before burning a broken binary
The goal: kill ghost builds. An app you can tap, on your device, from day one — not just a preview in a sandbox.
How to ship a Fitness kit app — real flow, real devices
Clone the Fitness kit. Swap name, icon, env vars. Run:
pnpm otf-kit setup:mobile
pnpm otf-kit build:mobile
You’re prompted for your Apple/Play developer credentials and team id (or pull from local env). The setup script wires:
-
eas.jsonwith your team/bundle ids - Store icons/splash pulled from your assets folder
- Privacy manifest and push notification keys
- Overwrites dummy secrets with your .env.[platform] file
Build artifacts are ready for direct upload:
-
*.ipafor TestFlight, with install guide -
*.aabfor Play Console, with rollout checklist
No ad-hoc code signing, no “search the docs”, no missing builds. If any step fails, it tells you why and how to unblock.
What this enables: idea to TestFlight in one day
The deploy wall is where most indie or side project efforts die, because the brain cost of thread-hopping between permissions, keys, Apple docs, and Expo errors is unrecoverable. By baking the deploy scripts and assets into the kit, you’re shipping a real product, not a toy.
- Iterate on your app, not your config
- Launch on TestFlight same-day, get real user feedback and App Store device installs
- Onboard trainers and clients on Android without leaking APIs or shipping unfinished builds
- Show up in the App Store, not just Expo Go
No more “almost there” — it’s real, or it isn’t.
[[COMPARE: Expo Go preview vs real device build pipeline]]
The real lesson: a template’s value is the production script, not the demo
Code that runs in a simulated shell is easy. The measure of a cross-platform template is whether it gets you all the way — signed, reviewed, tap-to-install, on real devices. OTF’s Fitness kit bakes the last mile in, so you don’t spend your launch week on “how do I sign a build, again?” The only template that counts is one that ships, out of the box.
Top comments (0)