RORK LABJP
COMPANION — The Rork Companion app lets you test your build on a real iPhone without paying for an Apple Developer account firstSEED — Rork raised a $15 million seed round in April 2026 led by Left Lane Capital, with Peak XV, True Ventures, Goodwater, and existing investor a16z Speedrun taking partPAPER — Rork acquired the app builder Paperline to bring in engineering talent, and says it plans to stay acquisitiveARR — Rork Max reportedly reached $1.5 million in ARR within three days of its February 2026 launchNATIVE — Rork Max reaches AR and LiDAR scanning, Metal-backed 3D games, Dynamic Island, Live Activities, HealthKit, NFC, and on-device Core MLPLATFORM — Targets include iPhone, iPad, Apple Watch, Apple TV, and Vision Pro, plus iMessageCOMPANION — The Rork Companion app lets you test your build on a real iPhone without paying for an Apple Developer account firstSEED — Rork raised a $15 million seed round in April 2026 led by Left Lane Capital, with Peak XV, True Ventures, Goodwater, and existing investor a16z Speedrun taking partPAPER — Rork acquired the app builder Paperline to bring in engineering talent, and says it plans to stay acquisitiveARR — Rork Max reportedly reached $1.5 million in ARR within three days of its February 2026 launchNATIVE — Rork Max reaches AR and LiDAR scanning, Metal-backed 3D games, Dynamic Island, Live Activities, HealthKit, NFC, and on-device Core MLPLATFORM — Targets include iPhone, iPad, Apple Watch, Apple TV, and Vision Pro, plus iMessage
Articles/Dev Tools
Dev Tools/2026-07-30Advanced

What Renovate may bump in an Expo app, and what it must never touch

Turning on automated dependency updates in a Rork-generated app also hands Renovate the 123 packages Expo SDK 57 pins. Measured on 2026-07-30, six of them sit a full major version behind npm latest. Here is how to generate the ignore list from the SDK instead of maintaining it by hand.

Rork523Expo153Renovatedependencies2Expo SDK 572CI4React Native215maintenance3

Premium Article

Monday morning, a row of Renovate pull requests was waiting in the repository.

One of them caught my eye: react-native-gesture-handler, from 2.32.0 to 3.1.0. A full major version.

CI was green. Unit tests passed, types checked, the linter had nothing to say. When you maintain six apps on your own, a green dependency PR is normally a small gift. Anything that gets updated without your hands on the keyboard is welcome.

Except this app is managed by Expo. And running expo install --check reports that the exact version Renovate wanted to install does not match the SDK.

The machinery meant to keep dependencies fresh was quietly working as machinery for breaking them.

Before chasing the root cause, I wanted the blast radius. How many Expo-managed dependencies can Renovate actually reach?

Expo pins 123 packages

The Expo SDK package ships a file called bundledNativeModules.json. It is what expo install consults to decide the version range for a given package, which makes it the compatibility contract for that SDK release.

I pulled the real file and counted. Measured on 2026-07-30.

npm pack expo@57.0.9 && tar -xzf expo-57.0.9.tgz
node -e 'console.log(Object.keys(require("./package/bundledNativeModules.json")).length)'
# => 123

Doing the same for SDK 56.0.18 gives 122 entries. The difference between 56 and 57 is a single addition, expo-eas-client.

But 90 entries had their version range changed. Almost nothing was added or removed, yet nearly three quarters of the ranges moved. An SDK bump is not a change of which packages exist. It is a wholesale rewrite of what versions they may be.

That much I expected. The next count was where my assumptions broke.

The dangerous ones are the packages that don't look like Expo

I split the 123 entries by name.

node -e '
const m = require("./package/bundledNativeModules.json");
const all = Object.keys(m);
const looksExpo = all.filter(n => n.startsWith("expo"));
console.log("total:", all.length, "expo*:", looksExpo.length, "other:", all.length - looksExpo.length);
'
# => total: 123 expo*: 82 other: 41

Forty-one entries do not begin with expo. react-native-reanimated. @shopify/flash-list. @sentry/react-native. react-native-svg. They look like ordinary packages published independently on npm.

From Renovate's point of view they are ordinary packages. Nothing in the package name or the manifest records that Expo is holding their version.

So I measured how far those 41 have drifted from npm latest.

// audit.mjs — classify the gap between Expo-pinned and npm latest for non-expo-* packages
import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";
 
const bnm = JSON.parse(readFileSync("./package/bundledNativeModules.json", "utf8"));
const names = Object.keys(bnm).filter((n) => !n.startsWith("expo-") && n !== "expo");
 
const num = (v, i) => Number(String(v).replace(/^[~^><= ]+/, "").split(".")[i]);
 
const rows = [];
for (const n of names) {
  let latest = null;
  try {
    latest = execSync(`npm view ${n} version`, { encoding: "utf8", timeout: 40000 }).trim();
  } catch {
    // Fall through to unknown. Throwing here would discard every result collected so far.
  }
  if (!latest) {
    rows.push({ n, pinned: bnm[n], latest: "n/a", gap: "unknown" });
    continue;
  }
  const gap =
    num(latest, 0) > num(bnm[n], 0)
      ? "MAJOR"
      : num(latest, 1) > num(bnm[n], 1)
        ? "minor"
        : latest !== String(bnm[n]).replace(/^[~^]/, "")
          ? "patch"
          : "same";
  rows.push({ n, pinned: bnm[n], latest, gap });
}
 
const count = (g) => rows.filter((r) => r.gap === g).length;
console.log(`managed(non expo-*): ${names.length}`);
console.log(
  `MAJOR=${count("MAJOR")} minor=${count("minor")} ` +
    `patch=${count("patch")} same=${count("same")}`,
);
for (const g of ["MAJOR", "minor"]) {
  console.log(`--- ${g} ---`);
  for (const r of rows.filter((r) => r.gap === g)) {
    console.log(`${r.n}\t${r.pinned}\t${r.latest}`);
  }
}

The output:

managed(non expo-*): 41
MAJOR=6 minor=9 patch=9 same=17 unknown=0

Six major gaps. Here they are.

PackagePinned by Expo SDK 57npm latest
@react-native-async-storage/async-storage2.2.03.1.1
react-native-gesture-handler~2.32.03.1.0
react-native-get-random-values~1.11.02.0.0
react-native-webview13.16.114.0.1
@sentry/react-native~7.11.08.20.0
react-native-bootsplash^6.3.107.3.2

Reading that list gave me a small chill.

Persistence, gestures, randomness, WebView, crash reporting, launch screen. Every one of them fails in a way that leaves CI green. A major bump to AsyncStorage touches saved user data. A gesture handler bump touches navigation. A Sentry bump touches the very system that is supposed to tell you something broke.

The nine minor gaps are worth listing too. They will not break anything immediately, but expo install --check flags them just the same.

PackagePinned by Expo SDK 57npm latest
@expo/vector-icons^15.0.215.1.1
@stripe/stripe-react-native0.64.00.72.0
react-native-keyboard-controller1.21.91.22.2
react-native-maps1.27.21.29.0
react-native-worklets0.10.10.11.3
react-native-safe-area-context~5.7.05.8.0
sentry-expo~7.0.07.2.0
@shopify/react-native-skia2.6.22.10.1
@shopify/flash-list2.0.22.3.2

My working assumption had been that excluding anything starting with expo- would cover most of the risk. The measurement says the opposite: filtering by name misses all six of the dangerous ones, because not one of the six begins with expo.

Auditing the same dependency set for supply-chain reasons is a different exercise with different questions; I wrote that up separately in auditing the dependencies of a Rork-generated app.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Expo SDK 57 pins 123 packages, and 41 of them do not start with expo-. Every one of those 41 is measured against npm latest here: 6 major-version gaps, 9 minor
A complete script that derives the ignore list from the installed SDK and exits 1 on drift, with execution logs showing it is idempotent and why bumping the SDK does not change the list
The trap that expo itself is absent from its own bundledNativeModules.json, what breaks when you miss those three lines, plus the renovate.json that governs whatever is left
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-07-28
Counting what prebuild --clean will erase before you upgrade to Expo SDK 57
A raw diff between two generated ios/ trees showed 649 changed lines; only 3 were real edits. How to count what prebuild --clean erases, and move it into a config plugin.
Dev Tools2026-03-30
Fixing Expo Dependency Errors in Rork Apps
A practical guide to resolving Expo dependency conflicts and errors in Rork-generated applications. Learn to fix version mismatches, installation failures, and compatibility issues.
Dev Tools2026-07-27
When to Raise Your Minimum iOS Version — Count Leftover Branches, Not User Percentages
Judging a minimum OS bump by usage share produces the same answer every year, so the decision never happens. Here is the annotation convention, the sweep script that counts how many branches each candidate floor would retire, and what to watch for 30 days after.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →