Everything needed to test NutriSync on real phones and publish it to the App Store and Google
Play, using Expo Application Services (EAS). Written for the current Expo SDK 54 project
in the githubjuanjose/nutrisync-app repo (React Native 0.81, React 19.1; requires
Node ≥ 20.19.4).
Key project facts (July 2026):
- EAS project id: 3b124e7e-e7e8-43ed-a54c-b660a07109dc
- Bundle / package id: com.nutrisync.app
- OTA updates URL: https://u.expo.dev/3b124e7e-e7e8-43ed-a54c-b660a07109dc (in app.json)
- runtimeVersion policy: appVersion
- OTA is already wired: every push to nutrisync-app runs eas update --branch production.
| Account | Cost | Why |
|---|---|---|
| Expo account | Free | Runs EAS Build/Submit/Update. Sign up at expo.dev. |
| Apple Developer Program | $99 / year | Required to build a real iOS app, use TestFlight, and ship to the App Store. This is the current iOS blocker — a free Apple account has no "team" and cannot sign or distribute. |
| Google Play Console | $25 one-time | Required to publish on Android / Play internal testing — not needed for APK testing. |
You can do all Android testing — the preview APK below — before paying for anything. The Apple fee is the one thing standing between us and iOS TestFlight.
npm install -g eas-cli
eas login # sign in to the shared Expo account
git clone https://github.com/githubjuanjose/nutrisync-app
cd nutrisync-app
npm install
The project is already linked to EAS (project id 3b124e7e-e7e8-43ed-a54c-b660a07109dc is in
app.json), so you do not need to run eas init on this repo. On a brand-new project you
would run eas init to create the id and write it into app config.
Node version matters. SDK 54 needs Node ≥ 20.19.4. If installs or builds fail with obscure errors, check
node -vfirst — Node 18 will not work.
npx expo start # same Wi-Fi: scan the QR with Expo Go
npx expo start --tunnel # remote testers, via Expo's servers (ngrok — flaky)
Scan the QR with the Expo Go app (iOS App Store / Google Play). Live reload on save. This is for developers iterating, not for stakeholder testing: Expo Go does not receive OTA updates and can't run custom native modules (e.g. HealthKit), so once wearable connectors land you must use a development build (next section). For the Madrid testers, prefer the preview APK in section 4.
A development build is your own app binary with the dev tools baked in — needed once we add native modules (HealthKit, Health Connect, biometrics).
# iOS (installs to registered devices or a simulator)
eas build --profile development --platform ios
# Android (installs an .apk on any device)
eas build --profile development --platform android
EAS returns a URL/QR; open it on the phone to install. Then run npx expo start --dev-client
and the build connects to your Metro bundler.
For iOS physical devices you must register them first (this needs the paid Apple account):
eas device:create # sends a link the tester opens on their iPhone
This is the recommended path for the Madrid testers. The preview profile is configured for
internal distribution with buildType: apk, so a single command produces a standalone
Android install anyone can run without Expo Go or Metro.
eas build --profile preview --platform android
.apk plus a download page with a link and QR — share it, tap to install.For iOS, internal distribution requires the testers' devices registered on the paid Apple
account (eas device:create), or — smoother — TestFlight (section 6).
preview profile (in eas.json){
"build": {
"preview": {
"distribution": "internal",
"android": { "buildType": "apk" }
},
"production": {}
}
}
eas build --profile production --platform all
Produces an .aab (Android App Bundle) and a .ipa (iOS). autoIncrement bumps the build
number each time. Credentials (signing keys, provisioning) are generated and stored by EAS —
say yes when it offers to manage them. iOS builds need the paid Apple account.
eas submitFill the placeholders in eas.json → submit.production first (Apple ID, App Store Connect app
id, Apple Team id; Android service-account JSON).
# iOS → App Store Connect / TestFlight
eas submit --platform ios --latest
# Android → Play Console (internal track by default)
eas submit --platform android --latest
TestFlight is the way to get the app on iPhones, but it needs the paid Apple Developer Program
($99/yr). A free Apple account has no team and cannot sign or distribute — so enrollment is
the prerequisite. Once enrolled:
1. In App Store Connect create the app (bundle id com.nutrisync.app).
2. Build for iOS and submit:
eas build --platform ios --profile production
eas submit --platform ios --latest
The build appears in TestFlight after Apple processing (~15 min).
3. Add testers. Internal testers (your team) install immediately; External testing
triggers a one-time Beta App Review.
4. Export compliance is pre-answered (ios.config.usesNonExemptEncryption = false), so there's
no per-build encryption questionnaire.
com.nutrisync.app).eas.json (git-ignored).eas submit pushes to the internal testing track → add testers by email. (For simple beta
testing you can skip all of this and just share the preview APK from section 4.)This part is done. Think of the GitHub Action as a conveyor belt: push to nutrisync-app →
the app updates itself on every installed build, no rebuild and no store review.
.github/workflows/eas-update.yml, which runs eas update --branch production
on every push (auth via the EXPO_TOKEN secret).eas update --branch production --message "onboarding copy fix"runtimeVersion policy is appVersion, so an OTA only lands on builds with a matching app
version. Native changes still need a fresh build.app.json.NSHealthShareUsageDescription) once
HealthKit is added; HealthKit data must not be used for advertising.app.json → version is the user-facing version (e.g. 1.0.0) and, via the appVersion
runtimeVersion policy, also gates which builds an OTA update reaches.autoIncrement in the production profile.version for each store release; use eas update for in-between JS patches.npm run typecheck (or CI) is green; confirm Node ≥ 20.19.4 and SDK 54.nutrisync-app → the Action ships an OTA to production; smoke test on a preview APK.eas build --profile production --platform all (iOS needs the paid Apple account).eas submit --platform ios --latest and/or --platform android --latest.eas update --branch production for hotfixes after launch.