Personal training app — an Expo / React Native iOS app with a deterministic workout engine. This README covers running it in development and deploying a standalone build to your iPhone.
Bundle id: au.angus.forge · Expo SDK 56 · React Native 0.85
- Node (
node -v) and the repo deps:npm install - Xcode + Command Line Tools (for the iOS simulator and standalone builds)
- CocoaPods (
pod --version) — only needed for standalone builds - For on-device standalone installs: a free Apple ID + SideStore (or AltStore) on the iPhone — see Deploy
Fast inner loop with live reload. The app runs inside Expo Go and is tethered to the Metro dev server on this machine (it loads the JS bundle over the network at launch).
npm install
npx expo start # then press i for simulator, or scan the QR on devicenpx expo start --ios
⚠️ On this machineexpo start --ioscan crash withNot authorised to send Apple events to System Events— a macOS Automation (TCC) permission, not an app bug. Two fixes:
- Grant it once: System Settings → Privacy & Security → Automation → allow your terminal to control System Events and Simulator. Then
--iosworks.- Or drive the simulator directly (no AppleScript needed):
First launch installs Expo Go automatically; screenshot withxcrun simctl boot "iPhone 17 Pro" # any available device open -a Simulator npx expo start # leave running in another shell xcrun simctl openurl booted "exp://127.0.0.1:8081" # opens the app in Expo Goxcrun simctl io booted screenshot out.png.
- Install Expo Go from the App Store.
npx expo start— phone and computer on the same Wi‑Fi → scan the QR code.- Off your network (different Wi‑Fi / cellular):
npx expo start --tunnel.
Limitation: Expo Go is tethered. It needs this computer running Metro and reachable (LAN, or
--tunnel+ internet on both ends). It will not cold-start offline — so it's for development, not for using the app away from your computer (e.g. the gym). For that, build a standalone copy ↓
A standalone build embeds the JS bundle in the app binary, so once installed it runs fully offline — its own home-screen icon, no dev server, no network. This is the build to use at the gym.
scripts/build-ipa.sh # → dist/Forge.ipa (incremental)
scripts/build-ipa.sh --clean # wipe ios/, regenerate, clean buildWhat it does: expo prebuild (generates native ios/) → pod install → xcodebuild
Release for device with code signing disabled → wraps the .app into dist/Forge.ipa.
The .ipa is intentionally unsigned — SideStore/AltStore signs it on install.
- Set up SideStore on the iPhone (one-time, needs a computer once to pair). It signs apps with your free Apple ID and auto-refreshes the signature on-device — no computer or matching Wi‑Fi required after setup.
- Get
dist/Forge.ipaonto the phone (AirDrop, Files, or SideStore's import). - Open it in SideStore → install.
AltStore is the simpler-to-set-up alternative, but it ties refreshes to AltServer running on your computer on the same Wi‑Fi, so you'd need to be home with the Mac on weekly.
A SideStore/AltStore refresh only re-signs the existing build. When the code changes,
re-run scripts/build-ipa.sh and reinstall the new .ipa.
- Free Apple ID signing: the cert expires every 7 days — SideStore/AltStore must refresh within that window or the app stops launching until refreshed.
- Free account caps: max 3 sideloaded apps active at once, 10 app IDs / 7 days.
- A genuinely frictionless "install once, lasts a year" build needs the Apple Developer Program ($99/yr); not required for personal use if you accept the 7-day refresh.
The macro engine has a unit suite (Node's built-in runner — no jest/babel needed):
npm test # run test/macro.test.mjs (volume templates, derived intensity,
# correlation flip, F_slow coupling, adapter invariants, config round-trip)
npm run macro:dump # regenerate docs/macro-results.json (full plan snapshot)How it works + the numbers: docs/macro-engine-how-it-works.md, docs/macro-params.json
(inputs), docs/macro-results.json (outputs). A small resolve hook (test/setup.mjs) lets
Node import the app's extensionless imports.
| Path | What |
|---|---|
App.js, index.js |
entry points |
src/ |
app code — engine, screens, components |
src/macroFormula.js · src/macroAdapter.js |
macro program engine (template model) |
src/orchestrator.js · src/micro.js · src/engine.js |
daily session generation |
exercises.json |
exercise library (seeded into SQLite) |
scripts/build-ipa.sh |
standalone .ipa builder |
docs/ |
design + macro-engine handoffs |
ios/, android/, dist/ |
generated/build output (gitignored) |