---
title: Expo SDK 58 Beta is now available
authors: Alan Hughes, Brent Vatne
published: September 15, 2026
---

**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](https://github.com/expo/expo) to learn more about the scope of the release and any breaking changes. We'll merge all changelogs into the root [**CHANGELOG.md**](https://github.com/expo/expo/blob/main/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](https://expo.dev/go)). 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](https://chat.expo.dev/) 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](https://github.com/expo/expo/pull/46733)). This changes how app delegate callbacks are delivered, so read the [scene life cycle migration guide](https://expo.fyi/ios-scene-lifecycle) if you customize **AppDelegate.swift**. Expo packages no longer read geometry from `UIScreen.main` ([#48172](https://github.com/expo/expo/pull/48172), [#48315](https://github.com/expo/expo/pull/48315), [#48316](https://github.com/expo/expo/pull/48316), [#48170](https://github.com/expo/expo/pull/48170), [#48169](https://github.com/expo/expo/pull/48169)), and `expo-modules-core` has scene-aware geometry helpers ([#48168](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48175)). See [Orientation locks on iOS 27 and later](https://docs.expo.dev/versions/v58.0.0/sdk/screen-orientation/#orientation-locks-on-ios-27-and-later). [`expo-glass-effect`](https://docs.expo.dev/versions/v58.0.0/sdk/glass-effect/) reports `isLiquidGlassAvailable` as `true` in apps built with the iOS 27 SDK ([#49850](https://github.com/expo/expo/pull/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](https://docs.expo.dev/build-reference/infrastructure/) 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](https://github.com/expo/expo/pull/46757), [#46809](https://github.com/expo/expo/pull/46809)). If you'd rather not leave your editor, the new [`expo-device-hub`](https://github.com/expo/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](https://expo.dev/services/simulators), our upcoming service for cloud simulators.

![The expo-device-hub dashboard in a browser: a sidebar listing an iPhone 17 Pro Max simulator on iOS 27 and a Pixel 9 emulator, a live stream of the app in the middle, and a panel with CPU, memory, and network graphs and device options such as appearance, Liquid Glass, text size, and accessibility toggles.](https://cdn.sanity.io/images/9r24npb8/production/7ca552a9e2926f63c9fb96a1d67052927f6486df-2000x1700.png)

## **App Intents: expose your app to Siri and Apple Intelligence**

[`expo-app-intents`](https://docs.expo.dev/versions/v58.0.0/sdk/app-intents/) exposes Apple App Intents (Siri, Shortcuts, Spotlight, and Apple Intelligence) from Expo apps ([#47207](https://github.com/expo/expo/pull/47207)). App Intent types are declared in Swift [inline modules](https://docs.expo.dev/modules/inline-modules-reference/) 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](https://github.com/expo/expo/pull/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.

![Two iPhone screenshots. On the left, Siri asks 'Which task did you complete?' and lists onboarding tasks from the app such as 'Sign offer letter' and 'Upload ID documents'. On the right, Siri says 'Marking Upload ID documents as done' above the app's checklist, where that task is now checked.](https://cdn.sanity.io/images/9r24npb8/production/a9bf3062ecae5e551c5618fafd1df1529ad3d55d-2400x1760.jpg)

## **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](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/) and [Jetpack Compose](https://docs.expo.dev/versions/v58.0.0/sdk/ui/jetpack-compose/) galleries in the docs.

![Side by side grids of Expo UI component previews from the docs: SwiftUI components for iOS on the left and Jetpack Compose components for Android on the right](https://cdn.sanity.io/images/9r24npb8/production/2608c7b22d20d07e35c4cebe7d34e29bb01aebfe-2400x1554.png)

**iOS navigation.** [`@expo/ui`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/) adds `NavigationStack`, `Toolbar`, `NavigationLink` and `NavigationDestination` components, the `navigationTitle` modifier, and the `close` button role ([#49940](https://github.com/expo/expo/pull/49940), [#49991](https://github.com/expo/expo/pull/49991)). `NavigationSplitView` adds two and three-column layouts ([#50075](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48905), [#49621](https://github.com/expo/expo/pull/49621), [#49767](https://github.com/expo/expo/pull/49767), [#49838](https://github.com/expo/expo/pull/49838)). Also new: the `Background` component ([#48904](https://github.com/expo/expo/pull/48904)) and the `scrollClipDisabled` ([#49780](https://github.com/expo/expo/pull/49780)), `geometryGroup` ([#48838](https://github.com/expo/expo/pull/48838)), `listRowSeparatorTint` ([#48810](https://github.com/expo/expo/pull/48810)), `alignmentGuide` ([#49247](https://github.com/expo/expo/pull/49247)), `menuStyle` and `menuIndicator` ([#48448](https://github.com/expo/expo/pull/48448)) modifiers.

**Jetpack Compose.** New `Image` ([#48521](https://github.com/expo/expo/pull/48521)), `DateRangePicker`, `DateRangePickerDialog` ([#49788](https://github.com/expo/expo/pull/49788)) and `VerticalSlider` ([#49612](https://github.com/expo/expo/pull/49612)) components. `DropdownMenu` gains `cornerRadius` and `shadowElevation` ([#49515](https://github.com/expo/expo/pull/49515), [#49896](https://github.com/expo/expo/pull/49896)), and `RadioButton` gains `enabled` and `colors` ([#49852](https://github.com/expo/expo/pull/49852)).

**Universal components.** `BottomSheet` adds `contentPadding`, `containerColor` and `contentColor`, and `ListItem` takes a `colors` prop ([#48902](https://github.com/expo/expo/issues/48902), [#49575](https://github.com/expo/expo/pull/49575)). On web, `BottomSheet` drops the unmaintained `vaul` for an in-house HTML `<dialog>` ([#49509](https://github.com/expo/expo/pull/49509)).

**Hosted React Native views.** Views hosted inside `<RNHostView>` are now measured where SwiftUI and Jetpack Compose placed them ([#48969](https://github.com/expo/expo/pull/48969), [#48970](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48788)). The tap that closes a SwiftUI `Menu` no longer presses the React Native view underneath it ([#48463](https://github.com/expo/expo/pull/48463), [#49775](https://github.com/expo/expo/pull/49775)).

## **Expo and EAS Observe**

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

![The EAS Observe overview dashboard showing active users, sessions, and a release comparison table with time to interactive, time to first render, crash-free sessions, crash-free users, errors, and affected users for three releases.](https://cdn.sanity.io/images/9r24npb8/production/efd10d05674a536e2493a627e7b4a706775a5ed2-2560x1640.jpg)

## **`@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](https://docs.expo.dev/develop/development-builds/introduction/). They also had to know when to use Expo CLI and when to use EAS CLI. [`@expo/agent-cli`](https://github.com/expo/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_](https://github.com/kazutoyo) 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](https://github.com/expo/expo-agent-cli/issues).

## **Home screen widgets come to Android**

[`expo-widgets`](https://docs.expo.dev/versions/v58.0.0/sdk/widgets/) adds an Android implementation: widgets run their own JS bundle on a dedicated Hermes runtime, with support for interactions and Material Colors ([#46961](https://github.com/expo/expo/pull/46961), [#47035](https://github.com/expo/expo/pull/47035), [#48454](https://github.com/expo/expo/pull/48454)). On iOS, Live Activities gain a `staleDate` option on `LiveActivity.start()` and `update()` ([#46343](https://github.com/expo/expo/pull/46343)), stable ActivityKit identifiers ([#48589](https://github.com/expo/expo/pull/48589)), and runtime widget configuration changes ([#47533](https://github.com/expo/expo/pull/47533)).

## **Swift Package Manager builds**

React Native 0.87 added [experimental Swift Package Manager support](https://reactnative.dev/blog/2026/08/11/react-native-0.87) 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](https://github.com/expo/expo/pull/45906), [#49820](https://github.com/expo/expo/pull/49820), [#49821](https://github.com/expo/expo/pull/49821), [#49832](https://github.com/expo/expo/pull/49832)), and an Expo autolinking plugin for React Native's `npx react-native spm` pipeline is in review ([#49823](https://github.com/expo/expo/pull/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](https://expo.dev/blog/talking-to-jsi-in-swift) on iOS to make calls 1.6 to 2.3× faster, and [replaced reflection with a Kotlin compiler plugin](https://expo.dev/blog/how-a-kotlin-compiler-plugin-cut-android-time-to-first-render) 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](https://github.com/expo/expo/pull/49761)), passing long strings in either direction is up to 3.8× faster ([#49678](https://github.com/expo/expo/pull/49678)), and promises from async functions cost less to create and resolve ([#49718](https://github.com/expo/expo/pull/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](https://expo.dev/blog/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.

![Twelve Android microbenchmarks comparing a TurboModule, Expo Modules 1.0, and Expo Modules 2.0. Expo Modules 2.0 has the shortest bar in every benchmark, from calling a function with no arguments to emitting an event with an object.](https://cdn.sanity.io/images/9r24npb8/production/1604d42a3d76db25da068f0e4aafc7f4b19f3f04-2000x944.png)

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](https://expo.dev/blog/an-early-look-at-expo-modules-2-0) 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](https://github.com/expo/expo/pull/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](https://docs.expo.dev/versions/v58.0.0/sdk/fingerprint/#fingerprintpreset) 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](https://oxc.rs/) and exposed to Node.js through [napi-rs](https://napi.rs/). In our internal testing, per-module transform time was about 3× faster and end-to-end cold bundling about 2× faster ([#48443](https://github.com/expo/expo/pull/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.

![Two transform timelines for the same app. With Noxcturnal enabled, 5,477 files finish in 2.46 seconds of wall time. With Babel, 5,494 files take 5.26 seconds.](https://cdn.sanity.io/images/9r24npb8/production/8027fd69595a19751d65e223e65d1b89db8097bb-2000x728.png)

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](https://docs.expo.dev/router/web/data-loaders/), [server-side rendering](https://docs.expo.dev/router/web/server-rendering/), and [middleware](https://docs.expo.dev/router/web/middleware/) are now stable and no longer need experimental flags. [Native tabs](https://docs.expo.dev/router/advanced/native-tabs/), [toolbars](https://docs.expo.dev/router/advanced/stack-toolbar/), and the [standard navigation integration](https://docs.expo.dev/router/advanced/custom-navigators/) are also stable.

[Expo Router's](https://docs.expo.dev/versions/v58.0.0/sdk/router/) 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](https://github.com/expo/expo/issues) 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`](https://docs.expo.dev/router/migrate/sdk-57-to-58/#replace-freezeonblur) 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`](https://docs.expo.dev/router/migrate/sdk-57-to-58/#update-custom-routers) 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](https://github.com/expo/expo/pull/49174), while keeping the navigator mounted.
- **Optional dependencies**: on Android, install [`expo-symbols`](https://docs.expo.dev/versions/v58.0.0/sdk/symbols/) for `NativeTabs.Trigger.Icon` with the `md` prop and [`@expo/ui`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/) for `Stack.Toolbar`. These packages are now optional peer dependencies.

Review the [migration guide](https://docs.expo.dev/router/migrate/sdk-57-to-58/) 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](https://github.com/expo/expo/pull/47255), [#48997](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48098)). Expo CLI port selection is also more consistent, and non-interactive runs roll over to the next free port instead of failing ([#47771](https://github.com/expo/expo/pull/47771), [#48300](https://github.com/expo/expo/pull/48300)).

## **A faster, more reliable Expo CLI tunnel**

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

```bash
EXPO_UNSTABLE_TUNNEL_V2=1 expo start --tunnel
```

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](https://reactnative.dev/blog/2026/08/11/react-native-0.87) and the [React Native 0.88 release candidate](https://github.com/react/react-native/releases/tag/v0.88.0-rc.0). 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](https://reactnative.dev/blog/2026/08/11/react-native-0.87) and the [React Native 0.88.0-rc.0 release notes](https://github.com/react/react-native/releases/tag/v0.88.0-rc.0) 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](https://posthog.com/) 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](https://expo.dev/changelog/posthog-integration) and the [Using PostHog guide](https://docs.expo.dev/guides/using-posthog/).

## **Other notable changes**

- **`expo-camera`**: added `CameraView.scanDocumentAsync` for multi-page document scanning on Android and iOS ([#47362](https://github.com/expo/expo/pull/47362)).
- **`expo-file-system`**: added `File.digest()` for MD5/SHA-1/SHA-256/SHA-384/SHA-512 hashes ([#48089](https://github.com/expo/expo/pull/48089)), and `File.preview()` and `File.canPreview()` for native preview flows.
- **`expo-audio`**: added lockscreen controls with playlists ([#46020](https://github.com/expo/expo/pull/46020)) and WAV/PCM file recording with `AudioStream.startFileRecordingAsync` ([#46771](https://github.com/expo/expo/pull/46771)).
- **`expo-image`**: added `transition.skipOnCacheHit` to skip transitions for cached images ([#48181](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/49651)).
- **`expo`**: `URL` and `URLSearchParams` were rewritten with IDNA/TR-46 support ([#47813](https://github.com/expo/expo/pull/47813)), and `TextDecoder` was rewritten for speed ([#48877](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48129), [#48621](https://github.com/expo/expo/pull/48621), [#48432](https://github.com/expo/expo/pull/48432), [#49486](https://github.com/expo/expo/pull/49486), [#49487](https://github.com/expo/expo/pull/49487), [#49485](https://github.com/expo/expo/pull/49485)). [Learn more](https://docs.expo.dev/versions/v58.0.0/sdk/font/).
- **`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](https://github.com/expo/expo/pull/48313)), and notifications can be grouped with `threadIdentifier` ([#49429](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/49687)), and the config plugin gained a `largeIcon` property ([#49481](https://github.com/expo/expo/pull/49481)). [Learn more](https://docs.expo.dev/versions/v58.0.0/sdk/notifications/).
- **`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](https://github.com/expo/expo/pull/49849), [#49972](https://github.com/expo/expo/pull/49972), [#49988](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/49258)).

## **Deprecations**

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

## **Notable breaking changes**

- **React Native Strict TypeScript API**: React Native 0.87 makes the [Strict TypeScript API](https://reactnative.dev/docs/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](https://reactnative.dev/docs/strict-typescript-api#migration-guide), or hand it to an agent with the [migrate-to-strict-api skill](https://www.skills.sh/react-native-community/skills/migrate-to-strict-api). 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](https://reactnative.dev/blog/2026/08/11/react-native-0.87) and [0.88.0-rc.0](https://github.com/react/react-native/releases/tag/v0.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](https://github.com/expo/expo/pull/46733), [#46734](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/49925), [#50032](https://github.com/expo/expo/pull/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](https://expo.fyi/ios-scene-lifecycle).
- **`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](https://github.com/expo/expo/pull/48554), [#48741](https://github.com/expo/expo/pull/48741), [#48839](https://github.com/expo/expo/pull/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](https://docs.expo.dev/guides/environment-variables/).
- **Android app template**: [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) is now enabled by default in release builds through `android.enableMinifyInReleaseBuilds=true` in **gradle.properties** ([#50108](https://github.com/expo/expo/pull/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`](https://docs.expo.dev/versions/v58.0.0/sdk/build-properties/).
- **`expo-router`**: the [navigation core changes](#expo-router-stable-data-loaders-and-native-tabs-improved-core) 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](https://docs.expo.dev/router/migrate/sdk-57-to-58/) covers each change, and the [expo-router changelog](https://github.com/expo/expo/blob/main/packages/expo-router/CHANGELOG.md) has the full list.
- **`expo-file-system`**: `File.write()` is now async and returns a promise; use `File.writeSync()` for the previous behavior ([#45992](https://github.com/expo/expo/pull/45992)).
- **`expo-sqlite`**: libSQL support is removed — `syncLibSQL()` and `libSQLOptions` are gone ([#48543](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/49072)). See [Other notable changes](#other-notable-changes) for the other `expo-notifications` changes in this release.
- **`@expo/fingerprint`**: the default preset is now `balanced` ([#47668](https://github.com/expo/expo/pull/47668)).
- **`@expo/ui`**: on iOS, `<Host>` top-aligns its content instead of centering it, so a `flex: 1` host matches Android ([#47561](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48441)). On Android, the `style` prop is removed from `RNHostView`; use `modifiers` instead ([#48970](https://github.com/expo/expo/pull/48970)).
- **`expo-localization`**: on iOS, RTL is no longer force-enabled from the device locale with `supportsRTL`; layout direction follows `I18nManager` ([#48086](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/48640)).
- **`@expo/cli`**: browser-based login is now the default for `expo login`; use `--no-browser` or `--username`/`--password` for the previous behavior ([#46832](https://github.com/expo/expo/pull/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](https://github.com/expo/expo/pull/47202)).
- **Android Gradle Plugin**: Expo modules tooling is now compatible with AGP 9 ([#46766](https://github.com/expo/expo/pull/46766), [#46769](https://github.com/expo/expo/pull/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

```console
$ # npm
$ $ npx create-expo-app@latest --template default@next
$ # bun
$ $ bun create expo-app --template default@next
$ # pnpm
$ $ pnpm create expo-app --template default@next
$ # yarn
$ $ yarn create expo-app --template default@next
```

**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](https://github.com/expo/skills/tree/main/plugins/expo/skills/expo-upgrade) 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**:

```console
$ $ npx expo install expo@next --fix
```

- [**Read the SDK 58 documentation**](https://docs.expo.dev/versions/v58.0.0/) for full API references.

## **What to test**

- **Upgrade and test**: run `npx expo install expo@next --fix`, then consult the [Native project upgrade helper](https://docs.expo.dev/bare/upgrade/?fromSdk=57&toSdk=58) and [report any issues you encounter](https://github.com/expo/expo/issues/new?assignees=&labels=needs+review&template=bug_report.yml).
- **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](https://github.com/expo/expo/issues/new?assignees=&labels=needs+review&template=bug_report.yml).
- **Spot a docs gap?** [Let us know](https://github.com/expo/expo/issues/new?assignees=&labels=docs&template=documentation.yml&title=%5Bdocs%5D+).

## **How to report issues**

- **Use the correct issue template**: [open an issue](https://github.com/expo/expo/issues) and fill out the appropriate template, and include a [minimal reproducible example](https://stackoverflow.com/help/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!