Upgrading to Expo SDK 55: breaking changes, pnpm catalog, and the official Claude plugin
SDK 55 is a meaningful update: React 19.2, React Native 0.83.2, and the New Architecture promoted from opt-in to the only architecture. We upgraded the Storyie monorepo from SDK 54 to 55 and came away with a few lessons worth sharing — both about the breaking changes themselves and about how we used Expo's official upgrading-expo Claude plugin to handle most of the mechanical work.
TL;DR
What changed | Impact | Action |
|---|---|---|
| New Architecture is now mandatory and the only option | Delete the flag from |
| Top-level splash key replaced by | Move splash settings into the |
| Android edge-to-edge is now mandatory | Remove the prop; rely on |
React 19.1 → 19.2, RN 0.81 → 0.83 | Minor React changes; significant RN internal changes | Check native dependency compatibility |
- pnpm catalog keeps all SDK-related version bumps in one file — the upgrade was a single diff in
pnpm-workspace.yamlplus apnpm install. - The
upgrading-expoClaude plugin detected and handled the three config changes automatically. - Project-specific skills (
.claude/skills/) filled in what the plugin couldn't know — our actual dependency versions, monorepo layout, and custom config.
The three breaking changes that required real work
1. newArchEnabled removal
SDK 55 drops the New Architecture opt-in entirely. If app.config.ts still carries newArchEnabled: true, you need to remove it:
// app.config.ts
- newArchEnabled: true,
+ // newArchEnabled option was removed in SDK 55The code change is trivial. The implication is not: there is no bridge fallback in SDK 55. Any native module that wasn't fully New Architecture-compatible breaks at runtime. We had already validated our dependency surface when we initially enabled the New Architecture, so nothing broke. Projects that skipped that validation step should audit native modules before upgrading.
Also worth checking: CI scripts, environment variables, and build configs that reference newArchEnabled — even as a comment or a conditional — should be cleaned up to avoid confusion.
2. splash config migration
The top-level splash field in app.config.ts is gone in SDK 55. Configuration moves into the expo-splash-screen plugin entry in the plugins array. For reference, the field we removed looked like this:
// app.config.ts
- splash: {
- image: "./assets/images/splash_2732.png",
- resizeMode: "contain",
- backgroundColor: "#F5F0EC",
- dark: {
- image: "./assets/images/splash_2732-dark.png",
- backgroundColor: "#2A2520",
- },
- },Storyie supports dark mode splash screens, which made this slightly more involved — the plugin's option shape for per-scheme images and colors is different from the old dark: nesting. The upgrading-expo plugin knew the correct target shape and produced the right plugin configuration without us having to manually dig through the expo-splash-screen changelog.
3. Android edge-to-edge and StatusBar.backgroundColor
SDK 55 makes edge-to-edge layout mandatory on Android. Your app's content now extends behind the system status bar and navigation bar. As a consequence, the backgroundColor prop on StatusBar has no effect and logs a warning.
This is not just a config tweak — it's a layout design concern. If your screens relied on StatusBar.backgroundColor to create a visually distinct header area, you need to rethink that with proper SafeAreaView padding and inset-aware layout. For us, it meant auditing header components and checking that bottom-tab navigation accounted for the navigation bar inset. The long-term result is a more native-looking UI; the short-term cost is a focused layout pass.
4. React and React Native version bumps
React 19.2 is a minor change — the upgrade was invisible at the React API level. React Native 0.83, however, carries significant internal changes that affect native module interop. The most reliable way to validate this is to build and run on actual devices (not just simulators) after upgrading. Simulators can mask issues that surface on hardware, particularly around New Architecture JSI behavior.
pnpm catalog: why version management was a non-issue
Storyie uses pnpm workspace's catalog feature to centralize dependency versions. All SDK-related packages are declared once in pnpm-workspace.yaml:
# pnpm-workspace.yaml
catalog:
expo: ^55.0.0
expo-modules-core: ^55.0.0
react: 19.2.0
react-dom: 19.2.0
react-native: 0.83.2Each package.json that needs these packages references them as "expo": "catalog:" rather than specifying a version inline. When we upgraded, the entire version bump was a single edit to pnpm-workspace.yaml followed by pnpm install.
Without a catalog, the same bump would have required editing multiple package.json files across the monorepo — and missing one means a mixed-version state that produces mysterious build failures. If you are running a pnpm monorepo and haven't adopted catalogs yet, SDK upgrades are a good forcing function.
Semi-automating the upgrade with the upgrading-expo plugin
Expo publishes an official Claude Code plugin collection called expo-plugins. The upgrading-expo plugin in that collection gives Claude structured knowledge of SDK breaking changes and migration steps. You enable it in .claude/settings.json:
{
"enabledPlugins": {
"upgrading-expo@expo-plugins": true
}
}With the plugin active, we told Claude to upgrade to SDK 55 and handle the breaking changes. It:
- Detected
newArchEnabledinapp.config.tsand removed it — knowing this was a SDK 55 deprecation, not an accidental deletion. - Migrated the
splashconfig to the plugin format, including the dark mode configuration. - Updated the
cataloginpnpm-workspace.yamlrather than individualpackage.jsonfiles — the plugin understood our monorepo's dependency management approach. - Checked compatibility for libraries we use (
react-native-webview, etc.) against the SDK 55 / RN 0.83 matrix.
The plugin provides Expo common knowledge. What it doesn't know is project-specific: which SDK version we were on before the upgrade, what custom native modules we use, how our monorepo is structured. That context lives in our .claude/skills/ files:
.claude/skills/
├── expo-mobile/SKILL.md # Current SDK version, EAS config, native modules
├── monorepo-architecture/ # pnpm workspace layout, catalog conventions
└── ...After completing the upgrade, we updated the version references in expo-mobile/SKILL.md — so the next upgrade starts with accurate ground-truth rather than stale version numbers.
The combination that works: plugin (Expo's shared upgrade knowledge) + skills (your project's specific state). Neither is sufficient alone.
What we learned
Breaking changes in SDK upgrades are mostly deletions
Looking at SDK 55 as a whole: newArchEnabled removed, splash deprecated, backgroundColor dropped. The pattern across Expo upgrades we've done is that breaking changes tend to be about removing old config or deprecated APIs — you're "adding" very little, just cleaning up. This is actually good news for automation: determining what to remove is mechanical (compare the release notes against the current config), which is exactly what an AI tool with domain knowledge can do reliably.
Edge-to-edge needs design attention, not just a prop deletion
The StatusBar.backgroundColor removal is technically a one-line change, but it exposes a layout assumption that often runs deeper. Any screen that previously controlled status bar color as a design affordance needs to be rethought in terms of safe area insets and content extension. We found a few header components that needed an additional pass before the layout felt right. Budget time for this — it's not a five-minute fix if you have many screens.
Skipping SDK versions is possible but not recommended
We jumped 54 → 55, skipping the intermediate 54 release cycle. This worked for us because our native dependency surface is small (Lexical runs inside a "use dom" WebView, which isolates a lot of RN version sensitivity) and because CI caught issues quickly. For projects with deeper native dependencies, we'd recommend against it. The incremental path surfaces incompatibilities one version at a time, which is much easier to debug than finding a breakage and having to bisect two version jumps.
Takeaways
- pnpm catalog reduces SDK version management to a single file edit. If your monorepo doesn't use catalogs, this upgrade is a good time to start.
upgrading-expoplugin handles the mechanical config changes reliably when given the right project context. Pair it with project-specific Claude skills for best results.- Breaking changes lean toward removal —
newArchEnabled,splash,backgroundColor. Automation-friendly by nature. - Edge-to-edge on Android is a real design consideration, not just a prop swap. Audit your header and bottom navigation layouts before shipping.
- Validate on real devices after any major RN version bump — simulators mask issues that surface on hardware.
Related Posts
- Building a Cross-Platform Mobile App with Expo — the broader Expo setup context that this upgrade builds on
- Cross-platform Lexical with
use dom: monorepo gains and the bridges you still own — why Lexical in a WebView means SDK version bumps are less painful - Building a Monorepo with pnpm and TypeScript — the pnpm workspace and catalog conventions underpinning the upgrade workflow
Try Storyie
Storyie runs the same codebase on the web at storyie.com and on the iOS app. The SDK 55 upgrade was invisible to users — which is exactly how it should be.