A fake Expo storefront for demoing Codemagic Patch OTA updates. Tap Add to cart and checkout fails. Publish a JS fix via Patch, install the update prompt, and the button works.
- Local Codemagic Patch server already running (see the
codemagic-patchrepo) - Xcode Command Line Tools on your Mac
cmpatchCLI from the Patch monorepo
Verify Patch is reachable:
curl -fsS http://localhost:3000/healthThis app targets the local dev stack defaults:
| Setting | Value |
|---|---|
| App | demo-app |
| Deployment | staging |
| Deployment key | dev_local_deployment_key |
| API URL | http://localhost:3000 |
| Download base | http://localhost:9100/codemagic-patch |
| API token | cm_pat_local-dev-token-change-me-00000001 |
codemagic-patch.config.json is already initialized for this project.
cmpatch stores credentials locally after you sign in once. You do not need to pass a token on every release.
cmpatch login \
--server-url http://127.0.0.1:3000 \
--token cm_pat_local-dev-token-change-me-00000001 \
--non-interactiveCredentials are saved to ~/.codemagic-patch/credentials.json. After that, cmpatch release-react works without export CODEMAGIC_PATCH_TOKEN=....
If you still see auth errors, check the server URL matches what you logged into (http://127.0.0.1:3000, not the dashboard port 5173).
CocoaPods is installed. Because the repo path contains a space (cloned repos), local iOS builds use a symlink and a small patch script.
ln -sfn "/Users/zachgoldie/cloned repos/patch-demo-app" ~/patch-demo-app
cd ~/patch-demo-app
npm run demo:setup:iosdemo:setup:ios runs expo prebuild, patches Xcode scripts for the spaced path, and runs pod install.
cd ~/patch-demo-app
npm run demo:ios -- --device "iPhone 17 Pro"Always build from ~/patch-demo-app (the symlink), not the spaced path directly.
After changing native config in app.json, re-run npm run demo:setup:ios before building again.
localhost in the Patch URLs works because the simulator runs on your Mac, where Patch is listening.
At the top of App.tsx:
| Toggle | What it does |
|---|---|
CHECKOUT_BROKEN |
Intentional checkout bug. Flip to false and publish an OTA to demo the fix. |
CHECK_CONDITION |
When to look for updates: "on-launch", "on-resume", or "both". |
INSTALL_CONFIRMATION |
true shows Later / Install Now; false installs with no confirm UI (sync()). |
INSTALL_MODE |
How the install is staged (ON_NEXT_RESTART, IMMEDIATE, etc.). |
Ensure CHECKOUT_BROKEN is true at the top of App.tsx, then build and install a Release simulator build (npm run demo:ios).
Open the app and tap Add to cart. You should see a payment failure (intentional bug).
Flip the toggle locally:
// App.tsx
const CHECKOUT_BROKEN = false;Publish to your local Patch server (from the project root):
cd ~/patch-demo-app
npm run publish:otaOr call cmpatch release-react directly. Signed releases need a private key at patch-signing/patch-private-key.pem (gitignored). A cmpatch-private.pem symlink at the project root points at it so dashboard-generated commands that use the default path also work.
With the app still on the simulator, background it (Cmd+Shift+H) and return to foreground, or kill and relaunch.
An Update Available alert appears. Tap Install Now. The app reloads.
Tap Add to cart again. Checkout succeeds.
App.tsx Screen, demo toggles, Patch update flow
scripts/publish-ota.mjs Publishes a normal release to local Patch
codemagic-patch.config.json cmpatch project context
- Expo Go will not work. Patch requires a custom native build.
- Do not use Metro dev mode for the demo. Build Release so the app boots from the embedded JS bundle. That is the bundle an OTA update replaces.
- Keep
expo.versionat1.0.0so OTA releases match the native binary version.