Expo SDK 58 Beta is now available

Alan HughesAlan Hughes
Brent VatneBrent Vatne
Expo SDK 58 beta is now available. SDK 58 beta includes React Native 0.88 (Release Candidate)

The SDK 58 beta period begins today and will last three to four weeks. The beta is an opportunity for developers to test out the SDK and ensure that the new release does not introduce any regressions for their particular systems and app configurations. We will be continuously releasing fixes and improvements during the beta period.

SDK 58 is built for iOS 27, and you can ship with the beta if you want iOS 27 support in your app now. SDK 58 beta includes React Native 0.88 (Release Candidate). React Native 0.88 has not been released yet, so the beta uses the release candidate. We will move to the stable release when React Native 0.88 ships, and release SDK 58 shortly after. The full release notes for SDK 58 won't be available until the stable release, but you can browse the changelogs in the expo/expo repository to learn more about the scope of the release and any breaking changes. We'll merge all changelogs into the root CHANGELOG.md when the beta is complete.

Expo Go for SDK 58 is available today only through Expo CLI, for Android devices and emulators and iOS simulators, and through eas go for iOS devices (learn more). The App Store and Google Play versions of Expo Go will update to SDK 58 shortly after the stable release, so you have time to upgrade before the store version drops SDK 57 support.

We're also hosting office hours on Discord for those of you interested in helping test the release!

SDK 58 is built for iOS 27

iOS 27 requires the UIKit scene-based life cycle and makes iPhone apps resizable, and apps built with the iOS 27 SDK get both automatically. Expo apps now use the scene-based life cycle so they launch correctly on iOS 27 (#46733). This changes how app delegate callbacks are delivered, so read the scene life cycle migration guide if you customize AppDelegate.swift. Expo packages no longer read geometry from UIScreen.main (#48172, #48315, #48316, #48170, #48169), and expo-modules-core has scene-aware geometry helpers (#48168).

On iOS 27, requireFullScreen no longer opts your app out of resizing, and ScreenOrientation.lockAsync may have no effect while the app is resizable. The requireFullScreen config plugin is updated for this (#48175). See Orientation locks on iOS 27 and later. expo-glass-effect reports isLiquidGlassAvailable as true in apps built with the iOS 27 SDK (#49850).

We'll also ship improvements during the beta to ensure deep integration with iPhone Duo from day one, as soon as the iPhone Duo SDK is available to developers.

EAS Build images with Xcode 27 and with the SDK 58 toolchain are coming soon, and we'll update this post when they're available. Until then, the latest EAS Build image ships Xcode 26.6.

Device Hub support for Xcode 27

Xcode 27 replaces Simulator.app with Device Hub. Expo CLI detects Device Hub, boots simulators through it, and focuses the right device using its devices:// deep link (#46757, #46809). If you'd rather not leave your editor, the new expo-device-hub dev tools plugin turns your browser into a local device dashboard: a live stream of every iOS simulator and Android emulator that you can tap, swipe, and type into, boot and shut down controls, CPU, memory, and network graphs, and toggles for appearance, Liquid Glass, text size, and accessibility settings. Install it with npx expo install expo-device-hub, run npx expo start, and the link prints in your terminal. If you want the same experience without a local Xcode or Android Studio install, keep an eye on EAS Simulator, our upcoming service for cloud simulators.

expo-device-hub streaming an iPhone 17 Pro Max simulator running iOS 27. Source: Nathan Schroeder's post on X.

App Intents: expose your app to Siri and Apple Intelligence

expo-app-intents exposes Apple App Intents (Siri, Shortcuts, Spotlight, and Apple Intelligence) from Expo apps (#47207). App Intent types are declared in Swift inline modules in an app-intents directory, since Apple's build-time metadata extraction only sees code in the app target. The package delivers invocations to JavaScript and stores entity values. Run npx expo-app-intents init to set up the directory (#47223). This library is in alpha, and documentation and examples are coming soon.

Example: completing a task from Siri

An onboarding checklist app declares a "complete task" intent and a task entity. Ask Siri to complete a task, and Siri lists the tasks from the app and asks which one. Pick one, and the intent runs in your JavaScript and the app marks it done, all without foregrounding the app.

An App Intent exposed from an Expo app: Siri asks which task to complete, then runs the intent in the app.

Expo UI: native navigation on iOS, new Compose components, and more

Every component now has a visual in the docs

The Expo UI reference now shows a screenshot of every component next to its API, so you can see what you're picking before you read the props. Browse the SwiftUI and Jetpack Compose galleries in the docs.

A sample of the SwiftUI and Jetpack Compose component galleries in the Expo UI docs.

iOS navigation. @expo/ui adds NavigationStack, Toolbar, NavigationLink and NavigationDestination components, the navigationTitle modifier, and the close button role (#49940, #49991). NavigationSplitView adds two and three-column layouts (#50075).

SwiftUI. The background, tint, border, strokeBorder, containerBackground, presentationBackground and foregroundStyle modifiers now accept any ShapeStyle, so a view can be painted with a material or a gradient (#48905, #49621, #49767, #49838). Also new: the Background component (#48904) and the scrollClipDisabled (#49780), geometryGroup (#48838), listRowSeparatorTint (#48810), alignmentGuide (#49247), menuStyle and menuIndicator (#48448) modifiers.

Jetpack Compose. New Image (#48521), DateRangePicker, DateRangePickerDialog (#49788) and VerticalSlider (#49612) components. DropdownMenu gains cornerRadius and shadowElevation (#49515, #49896), and RadioButton gains enabled and colors (#49852).

Universal components. BottomSheet adds contentPadding, containerColor and contentColor, and ListItem takes a colors prop (#48902, #49575). On web, BottomSheet drops the unmaintained vaul for an in-house HTML <dialog> (#49509).

Hosted React Native views. Views hosted inside <RNHostView> are now measured where SwiftUI and Jetpack Compose placed them (#48969, #48970). This fixes dropped presses, gestures stolen from an enclosing scrollable, and missing touches inside BottomSheet, Popover, AlertDialog and DropdownMenu. Tapping outside a hosted text field now dismisses the keyboard (#48788). The tap that closes a SwiftUI Menu no longer presses the React Native view underneath it (#48463, #49775).

Expo and EAS Observe

EAS Observe monitors your app's performance and errors in production, and it has been generally available since August 20. In SDK 58, expo-observe adds Observe.registerIntegration (#48245), ObserveErrorBoundary and reportError (#47341, #47871), the errorHandlingEnabled option (#48506), an expo-image integration (#47145), and Observe.clientId, the EAS client ID recorded on every event (#49599). AppMetrics is deprecated in favor of Observe — see Deprecations.

The EAS Observe overview: startup metrics, crash-free rates, and errors compared across releases.

@expo/agent-cli: the new CLI designed for agents

Agents used to learn Expo the hard way: launch Expo Go and hit a runtime error if you add a native module Expo Go doesn't support, then guess to use a development build. They also had to know when to use Expo CLI and when to use EAS CLI. @expo/agent-cli is a new experimental CLI, built by agents and designed for agents. It sits on top of Expo CLI, EAS CLI, and expo-doctor, and falls back to Expo CLI, so you can ask your agent to use it as a replacement.

Some useful commands you can try: status answers Expo Go compatibility without starting the app. dev starts the app with one command, like a web framework starting a server and a browser. It takes care of when to build the app and tries the fastest way to get your app running. Commands print next steps, so agents know how to move on. smoke is dev, plus a screenshot, plus stop: it checks that you can actually start developing the app on your machine. skills:sync sets up co-located agent skills from node_modules in your project.

Start with npx @expo/agent-cli@latest agents:setup, then tell your agent to use @expo/agent-cli instead of Expo CLI.

If you prefer a shorter name, expo-agent-cli is available as an alias. Thanks to Kazutoyo Tokai for transferring the package name to us. This CLI is under active development, and we'll go into more detail in an upcoming blog post. In the meantime, try it out and let us know what you think.

Home screen widgets come to Android

expo-widgets adds an Android implementation: widgets run their own JS bundle on a dedicated Hermes runtime, with support for interactions and Material Colors (#46961, #47035, #48454). On iOS, Live Activities gain a staleDate option on LiveActivity.start() and update() (#46343), stable ActivityKit identifiers (#48589), and runtime widget configuration changes (#47533).

Swift Package Manager builds

React Native 0.87 added experimental Swift Package Manager support as an alternative to CocoaPods, and SDK 58 lays the groundwork for Expo apps to use it. Expo's iOS sources have been restructured so their Swift, Objective-C, and C++ compile as separate SwiftPM targets (#45906, #49820, #49821, #49832), and an Expo autolinking plugin for React Native's npx react-native spm pipeline is in review (#49823). We plan to publish it as a preview during the beta. CocoaPods remains the default and supported path, and precompiled Expo modules keep working there.

Expo Modules: faster builds, faster calls, simpler to write

Faster Android builds with prebuilt expo-modules-core

expo-modules-core now ships precompiled native libraries for Android. Previously, every clean build, CI run, and EAS Build compiled the C++ in libexpo-modules-core.so from source, the most expensive step of an Android build that uses Expo. The npm package now includes .so files for all four ABIs in debug and release variants. In our test on a blank SDK 58 project, a clean Android debug build for all four ABIs took about 80 seconds on an Apple M3 Pro. Skipping the expo-modules-core C++ compilation cut it to about 39 seconds, roughly half. The saving is larger on machines with fewer cores, such as CI runners. The removed compiler work adds up to over 10 minutes across the four ABIs, which a 12-core machine hides by running many files in parallel.

Faster Expo modules

A native module call isn't free. There's a fixed cost to crossing into Swift or Kotlin and converting the values that go each way, and on the cheap calls that's most of what you're paying for. SDK 56 went after this on both platforms: we dropped the Objective-C++ layer on iOS to make calls 1.6 to 2.3× faster, and replaced reflection with a Kotlin compiler plugin on Android, making Record conversion around 6× faster and cutting time to first render by roughly 30%.

SDK 58 takes another pass at the iOS side. Calls that pass or return simple values are cheaper (#49761), passing long strings in either direction is up to 3.8× faster (#49678), and promises from async functions cost less to create and resolve (#49718). There's nothing to adopt: update to SDK 58 and every Expo module gets faster, including the ones you didn't write.

Expo Modules 2.0 beta

The other half of the story is the API you write against. Instead of describing your native module inside the existing DSL definition, you can now write an ordinary Swift or Kotlin class and annotate the methods and properties you want to expose to JavaScript. There's nothing new to learn beyond a handful of annotations. It's a much better fit for coding agents too, since there's no custom DSL to explain first. It's just Swift and Kotlin, which models already know well.

It's faster again on top of the improvements above, since the annotations let us generate the most direct binding at build time instead of figuring one out at runtime. On the same SDK, synchronous calls are 2.5 to 5.6× faster than the DSL, measured on an iPhone 16 Pro in a Release build. An early look at Expo Modules 2.0 has the benchmark and covers the API in more depth.

On Android, the Kotlin side shows the same pattern, and this time we also measured against React Native's TurboModules. Across twelve microbenchmarks, Expo Modules 2.0 is faster than Expo Modules 1.0 in every case, from 1.2× for passing an array of 100 numbers to 39.9× for emitting an event with a number. It is also faster than a TurboModule in every case: a call with no arguments takes 112 ns against 2,837 ns, passing an array of 20 objects takes 10.7 µs against 149.8 µs, and emitting an event with an object takes 963 ns against 8,080 ns.

Android microbenchmarks for Expo Modules 2.0 against Expo Modules 1.0 and a TurboModule. Lower is better. The green labels compare 2.0 with 1.0.

SDK 57 shipped the iOS macros as an experiment. With SDK 58 beta, Expo Modules 2.0 is in beta on both iOS and Android. Documentation is coming during the beta period, and the early look blog post is the best guide until then.

Fewer unnecessary native rebuilds with the new fingerprint default

Bumping a version, or changing files inside node_modules, no longer means a new fingerprint. SDK 58 defaults fingerprint to the balanced preset (#47668). It ignores common cases like updating version in app.json, and hashes native modules by package name and version instead of their files and directories. The hash stays stable without extra config. Learn more about fingerprint presets if you want a different tradeoff.

Experimental: 2× faster cold bundling with a Rust-based transformer

Metro's cache keeps warm bundling fast, but cold bundles, whether a full project or a changed module, spend most of their time in Babel. SDK 58 introduces an experimental replacement: "Noxcturnal", a module transformer written in Rust on top of oxc and exposed to Node.js through napi-rs. In our internal testing, per-module transform time was about 3× faster and end-to-end cold bundling about 2× faster (#48443). On our largest test app, a cold bundle of roughly 5,500 files went from 5.26 seconds with Babel to 2.46 seconds with the new transformer, with 443 files still falling back to Babel.

Transform worker activity for a cold bundle of our largest test app, with the new transformer (top) and with Babel (bottom). Source: Phil Pluckthun's post on X.

Try it by setting experiments.noxcturnalTransformWorker in your app config. It only activates when your project has no custom transform worker or Babel plugins and presets, and it skips files that need the Reanimated or Worklets Babel transforms. This is early work: the implementation and the numbers may change before it's stable, and we plan to add configuration options so that more projects, including those with custom Babel transforms, can use it.

Expo Router: stable data loaders and native tabs, improved core

Data loaders, server-side rendering, and middleware are now stable and no longer need experimental flags. Native tabs, toolbars, and the standard navigation integration are also stable.

Expo Router's navigation core has also been reworked so that navigation state is deterministic and easier to reason about, and it no longer carries most of the forked React Navigation API. Most apps won't notice. If you built a custom navigator or import from expo-router/react-navigation, some APIs have moved or been removed. If one you need is missing, please open an issue and describe what you're trying to do.

Other changes are listed below. We'll add more documentation links soon.

  • Navigator migration: JavaScript Tabs, TopTabs, and Drawer now use the same standard-navigation integration as NativeTabs, making their behavior more consistent.
  • Loader caching: call setResponseHeaders({ 'Cache-Control': 'private, max-age=60' }) from expo-server inside a loader to let the client cache its response for 60 seconds.
  • React transitions and Activity: navigation uses React transitions to keep the current screen visible while the next one loads. Set activityEnabled on a navigator or screen, or wrap part of a screen in NavigationAwareActivity, to hide inactive content while preserving its state and cleaning up its effects.
  • Async routes on web by default: the expo-router config plugin now enables asyncRoutes for web automatically. Route files are split into separate JavaScript chunks, which the browser loads when navigating to those routes. Set asyncRoutes: { web: false } to disable this.
  • Custom router API: use extendRouter to override parts of a built-in router, or extendRouterActions to add handlers for custom navigation actions.
  • Screen error boundaries: set unstable_settings.screenErrorBoundary in a layout or pass <Stack unstable_screenErrorBoundary={MyErrorBoundary} /> to show fallback UI for a screen that throws, while keeping the navigator mounted.
  • Optional dependencies: on Android, install expo-symbols for NativeTabs.Trigger.Icon with the md prop and @expo/ui for Stack.Toolbar. These packages are now optional peer dependencies.

Review the migration guide when upgrading, especially if you use custom navigators or import from expo-router/react-navigation.

Connecting to dev servers through proxies and tunnels

If you run your dev server behind a proxy, on a remote machine, or over a tunnel, development builds should now connect to it reliably. Previously, the manifest a development build fetched on startup told it which bundle URL and debugger hostname to use, and those could point at an address the client couldn't reach when the server sat behind a proxy or was discovered over Bonjour. The manifest now uses relative URLs when the client supports them (#47255, #48997).

RCT_METRO_PORT was a compile-time macro frozen at 8081 in prebuilt React Native, so bare apps without expo-dev-client always talked to port 8081, and two such apps running at once answered each other's reload commands. Prebuild now writes the port to the RCTMetroPort key in Info.plist, which the app reads at launch (#48098). Expo CLI port selection is also more consistent, and non-interactive runs roll over to the next free port instead of failing (#47771, #48300).

A faster, more reliable Expo CLI tunnel

Expo CLI has a new tunnel implementation built on @expo/ws-tunnel 2.0 (#46696). It connects faster, holds the connection more reliably, and no longer needs @expo/ngrok. Try it with:

You'll need to be signed in to your Expo account (expo login) to use it.

The EXPO_UNSTABLE_TUNNEL_V2 flag will be dropped later in the SDK 58 beta and this will become the new default tunnel implementation.

React Native 0.88 (Release Candidate)

SDK 58 beta upgrades React Native from 0.86 to the 0.88 release candidate, so it picks up the changes from both React Native 0.87 and the React Native 0.88 release candidate. Highlights of 0.88 include:

  • Swift Package Manager tooling: the opt-in npx react-native spm command and SwiftPM package generation. CocoaPods remains the default and supported path.
  • fontVariationSettings on Text: an object syntax for setting variable font axes, which pairs well with the variable font support added to expo-font in this release.
  • ArrayBuffer in TurboModules: JavaScript ArrayBuffer values now have native representations on both Android and iOS, with an explicit byte-ownership contract.
  • React Native DevTools: experimental performance screenshots, and WebSocket inspection in the Network panel.

Refer to the React Native 0.87 release notes and the React Native 0.88.0-rc.0 release notes for the full picture. We will update this section with a link to the React Native 0.88 blog post when it is published.

PostHog integration

You can now set up PostHog in an Expo app with one command, and every event it captures knows which EAS update it came from. Run eas integrations:posthog:connect and EAS CLI creates or links your PostHog project, installs the SDK and its config plugin, and writes the environment variables to your project and to EAS. PostHog recognizes the eas/update_id, eas/build_id, eas/channel, and eas/runtime_version properties and links them back to expo.dev. This is an EAS CLI feature, so it works with any SDK version. Read the PostHog integration changelog and the Using PostHog guide.

Other notable changes

  • expo-camera: added CameraView.scanDocumentAsync for multi-page document scanning on Android and iOS (#47362).
  • expo-file-system: added File.digest() for MD5/SHA-1/SHA-256/SHA-384/SHA-512 hashes (#48089), and File.preview() and File.canPreview() for native preview flows.
  • expo-audio: added lockscreen controls with playlists (#46020) and WAV/PCM file recording with AudioStream.startFileRecordingAsync (#46771).
  • expo-image: added transition.skipOnCacheHit to skip transitions for cached images (#48181), and an svgVariables prop that substitutes values for the CSS custom properties an SVG source refers to with var(), so different parts of one document can be given different colors while the image stays a vector (#48663). Values are not limited to colors. SVG sources that use var() now render with their fallback values even without the prop.
  • expo-secure-store: added requireConfirmation on Android for authenticated reads and writes (#48556).
  • expo-dev-launcher: added disableFab=1 and disableAutoLaunch=1 URL params to hide the floating action button and prevent the dev menu from opening at launch (#49651).
  • expo: URL and URLSearchParams were rewritten with IDNA/TR-46 support (#47813), and TextDecoder was rewritten for speed (#48877).
  • expo-sqlite: ships a co-located agent skill that shares best practices with agents. Run npx @expo/agent-cli skills:sync to set it up in your project (#49867).
  • expo-font: added support for variable fonts across Android, iOS, and web, so a single font file can provide a family with several weights or styles. This works with useFonts, loadAsync, and the config plugin (#48129, #48621, #48432, #49486, #49487, #49485). Learn more.
  • expo-notifications: on iOS, notification center calls are forwarded to a UNUserNotificationCenterDelegate registered by another library, so expo-notifications and another push library can coexist in the same app (#48313), and notifications can be grouped with threadIdentifier (#49429). On Android, a new delivery: 'alarmClock' option on date and repeating triggers uses AlarmManager.setAlarmClock(), which OEM battery policies don't defer, for time-critical alarms (#49687), and the config plugin gained a largeIcon property (#49481). Learn more.
  • expo-location: we're rewriting expo-location around a location provider abstraction, with a simpler position API, position watchers, background location updates, and new permission options such as requesting temporary full accuracy on iOS (#49849, #49972, #49988). The rewrite will ship as an opt-in preview alongside the existing API, so nothing changes for current expo-location code in this beta. We'll share more once it's ready to try.
  • @expo/cli: Android Virtual Device (AVD) and adb management has been rewritten to be more resilient to failures (#49258).

Deprecations

  • expo-file-system: File.md5 is deprecated in favor of File.digest() (#48089).
  • expo-modules-core: NativeArrayBuffer is deprecated in favor of ArrayBuffer (#47106).
  • expo-observe: the AppMetrics export is deprecated in favor of Observe (#48901).
  • expo-sqlite: the useLibSQL config plugin property is deprecated and no longer has any effect (#48543).
  • @expo/ui: on iOS, backgroundOverlay is deprecated in favor of background (#49621), and the color parameter of border and strokeBorder is deprecated in favor of content (#49838).

Notable breaking changes

  • React Native Strict TypeScript API: React Native 0.87 makes the Strict TypeScript API the default. Deep imports from react-native/Libraries/* are now type errors, and some types changed shape, most visibly refs, which now use instance types such as ViewInstance and TextInputInstance. Follow the migration guide, or hand it to an agent with the migrate-to-strict-api skill. To defer the migration, set "customConditions": ["react-native", "react-native-legacy-deep-imports"] in tsconfig.json (keep "react-native", which expo/tsconfig.base already sets). This opt-out is removed after React Native 0.88, so plan to migrate during the SDK 58 cycle.
  • React Native API removals: InteractionManager (use requestIdleCallback), the Touchable root export, the NativeMethods types, the Modal animated prop, and the deprecated StatusBar backgroundColor, translucent, and networkActivityIndicatorVisible props are removed. ImageBackground is deprecated in favor of a View with an absolutely positioned Image. See the 0.87 and 0.88.0-rc.0 release notes for the full list.
  • iOS scene-based life cycle: the iOS 27 SDK requires the UIScene life cycle, so npx expo prebuild now generates SceneDelegate.swift and a UIApplicationSceneManifest entry in Info.plist, and the UIWindow is created by the scene delegate instead of in didFinishLaunchingWithOptions (#46733, #46734). Expo forwards URL, user activity, Handoff, life cycle, and quick action events to ExpoAppDelegate overrides and subscribers, so config plugins and modules built on those keep working (#49925, #50032). If you manage the ios directory by hand, have a bare React Native app, or override app delegate methods directly, see the migration guide.
  • NODE_ENV and environment files: every Expo CLI command now sets NODE_ENV to development or production before loading .env files and your app config, so a dynamic app.config.js and the .env cascade always agree on the mode (#48554, #48741, #48839). Previously, every command kept an inherited NODE_ENV if one was set, and expo config never set one at all, so NODE_ENV=test npx expo start loaded .env.test. An inherited value is now ignored, and that command loads .env.development. Jest still sets NODE_ENV=test in your tests, and @expo/env still resolves .env.test.local, .env.test, and .env there. See the environment variables guide.
  • Android app template: R8 is now enabled by default in release builds through android.enableMinifyInReleaseBuilds=true in gradle.properties (#50108). R8 shrinks, optimizes, and obfuscates Java/Kotlin code, which reduces app size and improves startup time. Apps are optimized with the proguard-android-optimize.txt preset. Libraries that rely on reflection may need ProGuard keep rules. To opt out, set android.enableMinifyInReleaseBuilds to false with expo-build-properties.
  • expo-router: the navigation core changes make navigation states and route keys deterministic, defer navigation dispatch until after commit, and remove a large portion of the forked react-navigation API surface. @expo/ui and expo-symbols are now optional peer dependencies. The migration guide covers each change, and the expo-router changelog has the full list.
  • expo-file-system: File.write() is now async and returns a promise; use File.writeSync() for the previous behavior (#45992).
  • expo-sqlite: libSQL support is removed — syncLibSQL() and libSQLOptions are gone (#48543).
  • expo-notifications: foreground notifications are now shown by default unless your setNotificationHandler says otherwise, and a slow handler no longer drops the notification (#49072). See Other notable changes for the other expo-notifications changes in this release.
  • @expo/fingerprint: the default preset is now balanced (#47668).
  • @expo/ui: on iOS, <Host> top-aligns its content instead of centering it, so a flex: 1 host matches Android (#47561). HStack, VStack and GlassEffectContainer now forward an unset spacing to SwiftUI as nil and use the system default spacing; pass spacing={0} to keep the previous layout (#48441). On Android, the style prop is removed from RNHostView; use modifiers instead (#48970).
  • expo-localization: on iOS, RTL is no longer force-enabled from the device locale with supportsRTL; layout direction follows I18nManager (#48086).
  • expo-media-library: on iOS, Asset.getUri() and AssetInfo.uri now resolve the current Photos version of a video; pass version: AssetUriVersion.ORIGINAL for the previous behavior (#48640).
  • @expo/cli: browser-based login is now the default for expo login; use --no-browser or --username/--password for the previous behavior (#46832).

Tool version bumps

  • Node.js: Expo tooling now requires Node.js 22.13 or newer on the 22 line, 24.3 or newer on the 24 line, or Node.js 26 and later. Odd-numbered releases such as 23 and 25 are not supported (#47202).
  • Android Gradle Plugin: Expo modules tooling is now compatible with AGP 9 (#46766, #46769).

Known regressions

  • None reported yet. We'll update this section as we learn more during the beta.

How to try out the beta release

Initialize a new project with SDK 58 beta

Note: create-expo-app will install dependencies with the package manager that you are using. For example, with npm when npx is used and yarn when yarn create is used.

Upgrade an existing project

Try using our expo-upgrade skill with Claude Code to upgrade your app to the beta. We appreciate reports for any issues that you encounter so we can further tune it in the coming weeks.

The following instructions explain the manual steps to upgrade your app.

  • Upgrade all dependencies to match SDK 58:

What to test

  • Upgrade and test: run npx expo install expo@next --fix, then consult the Native project upgrade helper and report any issues you encounter.
  • Build natively: build with EAS Build (the Xcode 27 and SDK 58 images are coming soon, see above), or if you have Xcode and Android Studio installed locally, try prebuilding and running: npx expo prebuild --clean and npm run ios and npm run android. Alternatively, try npx expo run. Any new issues? Please report them.
  • Spot a docs gap? Let us know.

How to report issues

  • Use the correct issue template: open an issue and fill out the appropriate template, and include a minimal reproducible example.
  • Identify the root cause if you can: it's always super helpful and helps expedite a fix.
  • Mention you're on the SDK 58 beta: we'll prioritize the issue accordingly.

Thank you for testing out the beta, we appreciate you!