Store Release
Submit iOS and Android releases and operate updates after launch.
Release is where the Expo template's pieces meet: production variant, store records, EAS credentials, legal URLs, privacy disclosures, RevenueCat products, Supabase webhooks, update gates, and OTA channel hygiene.
Pre-flight checklist
Before creating a production store build:
- Confirm
APP_VARIANT=productionso the bundle ID/package isexpo.soarstarter.comand the scheme issoar-starter-expo. - Replace app name, icon, adaptive icon, splash, and favicon assets.
- Run
pnpm generate:assetsafter changing the source icon set. - Replace
EXPO_PUBLIC_TERMS_URL,EXPO_PUBLIC_PRIVACY_URL, andEXPO_PUBLIC_EULA_URL. - Host the Universal/App Links files if
EXPO_PUBLIC_LINKING_DOMAINis set. - Review Android permissions in
app.config.ts:CAMERA,READ_MEDIA_IMAGES, andPOST_NOTIFICATIONS. - Review iOS usage strings for camera, photo library, Apple Sign-In, and ATT.
- Configure production Supabase URL/anon key, RevenueCat SDK keys, Sentry DSN, PostHog key, and store URLs.
- Deploy production Supabase Edge Functions and set Edge secrets.
- Make sure RevenueCat's webhook points at the production Supabase project.
- Confirm
eas.jsonproduction usesdistribution: "store",channel: "production", andautoIncrement: true.
iOS release
Create the iOS app record for:
Bundle ID: expo.soarstarter.comPrepare:
- App name, subtitle, category, screenshots, support URL, marketing URL, and privacy policy URL.
- Sign in with Apple capability, because the app includes Apple auth.
- In-app purchase products if you ship RevenueCat purchases.
- Sandbox testers and TestFlight tester groups.
- Associated Domains if you use Universal Links.
Build and submit:
eas build --profile production --platform ios
eas submit --profile production --platform iosThe first submit will ask for Apple credentials or App Store Connect API key
details because submit.production.ios is empty in the template.
Mention the review-relevant flows:
- Account deletion lives in Me -> Account & Security and calls the
delete-accountEdge Function. - Legal consent is versioned by
LEGAL_VERSION. - ATT is requested only from the permissions primer, separate from legal consent.
- Purchases are account-bound through RevenueCat and Supabase entitlements.
- Push sending is not enabled unless you add token persistence and a send path.
If a tester has an active Apple subscription and deletes the account, the app offers the subscription management URL before deletion.
Android release
Create the Android app for:
Package name: expo.soarstarter.comPrepare:
- App content, target audience, content rating, screenshots, feature graphic, privacy policy, and support contact.
- Google Play App Signing and an internal testing track.
- In-app products or subscriptions if you ship RevenueCat purchases.
- App Links asset links if you use
EXPO_PUBLIC_LINKING_DOMAIN. - Notification, camera, and photo/media permission explanations.
Build and submit:
eas build --profile production --platform android
eas submit --profile production --platform androidThe template's preview profile produces an APK for internal sharing. Production store builds are handled by EAS for Play submission.
Use the same data map as iOS, then adapt it to Google's categories. Be explicit about account data, diagnostics, analytics, purchases, and files users upload.
The client can configure the RevenueCat Android SDK, but the shipped Supabase
webhook currently ignores PLAY_STORE events. Extend the webhook before
promising Android purchases unlock Supabase entitlements.
Privacy map
| Service | Data involved | Disclosure notes |
|---|---|---|
| Supabase Auth | Email, auth identifiers, profile fields | Account creation, login, profile, account deletion |
| Supabase Database | Todos, profile, subscriptions, payments, sample upload metadata | User-owned data protected by RLS |
| Supabase Storage | Uploaded sample files and avatars | Files are stored under user-scoped paths |
| RevenueCat | App user ID, purchase history, product identifiers | Used for purchases; entitlement source of truth is Supabase |
| PostHog | Analytics events and device/app context when configured | Legal consent does not currently block PostHog initialization |
| Sentry | Crash reports, stack traces, device/app context when configured | Upload sourcemaps for readable production traces |
| Expo Notifications | Expo push token when retrieved | Token is not persisted by the shipped client |
| ATT | Tracking authorization status | iOS-only prompt from the permissions primer |
Post-release operations
Set store URLs after the listings exist:
EXPO_PUBLIC_APP_STORE_URL=
EXPO_PUBLIC_PLAY_STORE_URL=Then use the version gate deliberately:
| Key | Use |
|---|---|
EXPO_PUBLIC_LATEST_APP_VERSION | Soft prompt users to upgrade |
EXPO_PUBLIC_MIN_APP_VERSION | Force old app versions to upgrade |
EXPO_PUBLIC_APP_UPDATE_URL | Store or landing-page URL opened by the gate |
EXPO_PUBLIC_APP_UPDATE_MESSAGE | User-facing update copy |
EXPO_PUBLIC_APP_UPDATE_CONFIG_URL | Remote JSON override for update policy |
Use OTA updates only on the matching channel:
eas update --channel production --message "Fix production copy"Keep production, preview, and development channels separate. Do not publish unreviewed experimental changes to the production channel just because they are "only JavaScript".
