Upgrade an Expo app to the latest stable SDK with a practical migration workflow, compatibility validation, package replacement proposals, and a final QA checklist. Use when a project needs SDK upgrades, New Architecture readiness checks, dependency compatibility checks, variant-aware config migration, or iOS/Android build stabilization.
Resources
6Install
npx skillscat add jimvaneijk/23g-expo-upgrade-skill Install via the SkillsCat registry.
23G Expo Upgrade Playbook
Run this workflow when upgrading an existing Expo app to the latest stable SDK and validating it end-to-end.
Skill Composition
If $upgrading-expo is available in the environment, use it as the base workflow first.
Apply this playbook on top of that baseline for:
- project-specific exceptions,
- variant-aware configuration migration,
- package replacement proposals,
- final QA checklist output contract.
If $upgrading-expo is not available, continue with this playbook only.
Required Output Contract
Always return:
- A short summary of what was changed.
- A risk list (high -> low).
- A concrete checklist for manual QA.
- Package compatibility findings and replacement proposals for problematic libs.
Workflow
1) Baseline scan
Collect and summarize:
- Current
expo,react-native,reactversions. - Current native/deep-link/push/error-reporting libraries.
- Whether variants exist (for example via
app.variants.tsor similar config map). - Whether project is managed/prebuild and whether
ios/andandroid/are git-tracked. - Whether EAS is already configured (
eas.json, build profiles, env strategy).
Commands (adapt as needed):
cat package.json
rg -n "expo|react-native|react|sentry|firebase|notification|push" package.json
rg -n "variants|APP_VARIANT|bundleIdentifier|androidPackage" app.config.* app.*variants* src
test -f eas.json && cat eas.json2) Upgrade core SDK and aligned deps
Before running commands, execute the checks from $upgrading-expo (or replicate them if unavailable), including:
- SDK/dependency alignment,
- diagnostics (
expo-doctor), - breaking changes checklist,
- deprecated package migration checks,
- cache and prebuild hygiene.
Run:
npx expo install expo@latest
npx expo install --fixThen resolve mismatches reported by Expo installer.
3) Config migration and structure
Prefer dynamic config in app.config.ts.
If the project already has variants, preserve that shape and avoid unnecessary redesign.
If app.variants.ts exists, keep it as source of truth.
Do not force .env loading from config unless requested.
4) iOS Firebase static-linking stabilization (known exception)
If iOS Firebase Pod errors occur with modular headers/static linking, prefer declarative Expo config via expo-build-properties plugin.
Use this pattern in app.config.ts plugin config:
ios.forceStaticLinking: includeRNFBApp,RNFBMessaging,RNFBRCTEventEmitter.ios.extraPods: includeFirebaseCoreInternalwithmodular_headers: trueGoogleUtilitieswithmodular_headers: trueFirebaseCorewithmodular_headers: trueFirebaseInstallationswithmodular_headers: true
Avoid old custom Podfile patch scripts when this declarative config works.
5) Push + entitlements
If project uses RNFirebase messaging on iOS, ensure aps-environment entitlement is set (development or production per project policy).
6) Build and runtime validation
Use one of these validation paths:
Path A (fast local feedback): use prebuild to quickly test native generation and local boot.
Path B (team/release-like): use EAS builds when the team prefers not to run local prebuild.
Path A commands:
npx expo-doctor
APP_VARIANT=<variant> npx expo prebuild -p ios --clean
APP_VARIANT=<variant> npx expo prebuild -p android --cleanPath B commands (example):
npx expo-doctor
eas build --platform ios --profile <profile>
eas build --platform android --profile <profile>Then run at least one real app boot or install test artifact per key variant.
6b) EAS detection and migration path
Always check for existing EAS setup before adding anything.
If eas.json does not exist:
- Create
eas.jsonwith profiles aligned to project variants and release strategy. - Add minimal required profiles (
production+ at least one non-production/internal profile). - In the user-facing output, provide Expo.dev EAS setup guidance in English with official links:
- https://docs.expo.dev/build/setup/
- https://expo.dev/accounts/[account]/projects (replace with project/account context)
- https://docs.expo.dev/eas/environment-variables/
If eas.json exists:
- Preserve existing profile names and intent.
- Migrate profiles to match current variant model and updated config keys.
- Verify env variable mapping per profile (for example variant selection and secrets strategy).
- Do not break existing CI assumptions unless explicitly requested.
Validation:
- Ensure
eas.jsonis valid JSON and profiles are usable. - Ensure each active variant has a mapped EAS build strategy (direct profile or documented fallback).
- If team prefers EAS-first, prioritize EAS profile migration over local prebuild scripts.
- Ensure all EAS setup explanation is written in English.
7) Compatibility and replacement proposals
Identify dependencies that are:
- Unsupported/untested on New Architecture.
- Unmaintained.
- Breaking on current SDK.
For each problematic package, provide:
- Why it is risky.
- Recommended replacement.
- Migration impact (low/medium/high).
- Minimal migration steps.
Use references/package-replacements.md as output format.
8) Final checklist output
Generate checklist using references/qa-checklist-template.md.
Project-specific note captured from real migration
For this project, the working pattern includes:
- Variant-driven config.
- Firebase iOS stabilization using
expo-build-properties(forceStaticLinking+extraPodsmodular headers). - Keeping current app structure if stable.
Treat that as preferred default unless the user explicitly asks to redesign.
References
references/qa-checklist-template.mdreferences/package-replacements.mdreferences/exceptions-template.mdreferences/runbook-template.md