---
title: Expo SDK 58
authors: Alan Hughes, Brent Vatne
published: October 15, 2026
---

Today we're announcing the release of Expo SDK 58. SDK 58 is built for iOS 27 and includes React Native 0.88. Thank you to everyone who helped with beta testing.

> **Note**: Expo Go for SDK 58 on the Apple App Store and Google Play Store will be released within a few weeks. [Learn more](#expo-go).

## **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 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)).

### iPhone Duo support

Apps built with SDK 58 are ready for iPhone Duo on the day it is released. On iPhone Duo, iOS moves most bars and controls into a vertical rail on the right or left edge. Your app will also need to respond to changes in window size as the device is folded or an app is shown in split view on the inner display. Start with the basics:

- **Navigation**: Use Expo Router's [`Stack`](https://docs.expo.dev/versions/v58.0.0/sdk/router/stack/) and [`NativeTabs`](https://docs.expo.dev/versions/v58.0.0/sdk/router/native-tabs/), or SwiftUI views through Expo UI's [`<Host>`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/host/). They use the system's own navigation and tab bars, which iOS places for you on both displays.
- **Safe areas**: Safe area handling becomes more important, and you may need to add `<SafeAreaView>` in more places, such as inside scrollviews, to handle horizontal insets for iPhone Duo. Update [`react-native-safe-area-context`](https://docs.expo.dev/versions/v58.0.0/sdk/safe-area-context/) to the latest version via `npx expo install react-native-safe-area-context`.

![Two screenshots of the Expo Go Home tab on iPhone Duo. On the left, the folded outer display. On the right, the open inner display, where the content is a centered column. On both, the Enter URL and account buttons and the tab bar sit in the system's vertical bar on the right edge.](https://cdn.sanity.io/images/9r24npb8/production/c48f03c0df3a929eea6ee692d0f81d56ae2fc17f-1800x878.png)

Module authors who present popovers can use the new `SceneGeometry.anchorPopover` helper in `expo-modules-core` to anchor them correctly on any regular-width display ([#50433](https://github.com/expo/expo/pull/50433)).

For layout, Expo UI adds [`ArrangementView`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/arrangementview/), the SwiftUI container Apple recommends for iPhone Duo. It places a primary and a secondary view side by side or as an overlay, and adapts to the fold and the device pose.

To react to the hinge itself, use the new [`expo-hinge`](https://docs.expo.dev/versions/v58.0.0/sdk/hinge/) package. `useHinge()`, `getHinge()`, and `addHingeListener()` report the hinge angle and whether it is closed, partially open, or fully open, on iOS 27.1 and later and on Android 11 foldables. In SwiftUI, the [`onHingeChange`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/modifiers/#onhingechangehandler) modifier does the same for a single view, and a callback from `useWorkletCallback` runs on the UI thread to keep effects such as parallax smooth. Apple recommends hinge state for interactions and effects, such as a tabletop camera shutter, not for layout.

### 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 shutdown 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/8d497f5f524ed08db157b87ca2439241367380fe-1800x1530.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 your app’s actions and content to Siri, Shortcuts, Spotlight, and Apple Intelligence. Declare intents in Swift [inline modules](https://docs.expo.dev/modules/inline-modules-reference/) in an **app-intents** directory so Apple can discover them in the app target at build time. The package delivers invocations to JavaScript and stores entity data you update from JavaScript. Run `npx expo-app-intents init` to set up app-intents in your app. If you use coding agents, run `npx @expo/agent-cli@latest install expo-app-intents` to install the agent skill. [Learn more about agent skill setup](https://docs.expo.dev/versions/v58.0.0/sdk/app-intents/#agent-skill). The library is in [alpha](https://docs.expo.dev/more/release-statuses/#alpha).

The package also supports Spotlight indexing, intent donations for system suggestions, and identifying on-screen content with `appEntityIdentifier()` for Expo UI or `AppEntityView` for React Native. On-screen identification requires iOS 18.4 or later and Xcode 27 or later.

A version coming soon will support running [`expo-task-manager`](https://docs.expo.dev/versions/v58.0.0/sdk/task-manager/) tasks from intent handlers, so you can perform work in JavaScript and return a result to Siri without opening your app.

### Example: completing a task from Siri

For example, an onboarding checklist app can let Siri list its tasks and ask which one to complete.

![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/088d4ef984ff1d345de67b1ae6ca04c0d972757c-2928x2150.jpg)

## **Expo UI: recycling lists, native navigation on iOS, new Compose components, and more**

### Recycling lists for large data sets

[`List`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/list/#large-lists), [`LazyVStack`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/lazyvstack/#large-lists) and [`LazyHStack`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/lazyhstack/) on iOS, and [`LazyColumn`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/jetpack-compose/lazycolumn/#large-lists) and [`LazyRow`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/jetpack-compose/lazyrow/) on Android now virtualize and recycle rows ([#49975](https://github.com/expo/expo/pull/49975), [#50579](https://github.com/expo/expo/pull/50579), [#50258](https://github.com/expo/expo/pull/50258)). Instead of rendering every row up front, they render only the rows near the visible area and reuse them as you scroll.

Pass the items as `data`, a unique key for each item with `keyExtractor`, and a `children` function that returns the row. Use `List.ForEach`, `LazyVStack.ForEach` and `LazyHStack.ForEach` in SwiftUI, and `LazyColumn.Items` and `LazyRow.Items` in Jetpack Compose.

<!-- SwiftUI example -->
```tsx
import { Host, List, Text } from '@expo/ui/swift-ui';

function renderContact({ item }) {
  return <Text>{item.name}</Text>;
}

export function Contacts({ contacts }) {
  return (
    <Host style={{ flex: 1 }}>
      <List>
        <List.ForEach data={contacts} keyExtractor={contact => contact.id}>
          {renderContact}
        </List.ForEach>
      </List>
    </Host>
  );
}
```

See the best practices for large lists in [SwiftUI](https://docs.expo.dev/versions/v58.0.0/sdk/ui/swift-ui/list/#large-lists) and [Jetpack Compose](https://docs.expo.dev/versions/v58.0.0/sdk/ui/jetpack-compose/lazycolumn/#large-lists) before you switch.

### 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/26ef8f836b2a0e38b653342aff07535e770d821d-1800x1165.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)), and `ToolbarItem` takes `placement` and `visibilityPriority` ([#50360](https://github.com/expo/expo/pull/50360)).

**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)), and `scrollEdgeEffectStyle` ([#50367](https://github.com/expo/expo/pull/50367)) 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 inside `<RNHostView>` are now measured where SwiftUI and Jetpack Compose place them, so `measure()` returns correct values and touches work inside `BottomSheet`, `Popover`, `AlertDialog` and `DropdownMenu` ([#48969](https://github.com/expo/expo/pull/48969), [#48970](https://github.com/expo/expo/pull/48970), [#50715](https://github.com/expo/expo/pull/50715), [#50727](https://github.com/expo/expo/pull/50727)). Tapping outside a hosted text field dismisses the keyboard ([#48788](https://github.com/expo/expo/pull/48788)), and closing a SwiftUI `Menu` no longer presses the view underneath it ([#48463](https://github.com/expo/expo/pull/48463), [#49775](https://github.com/expo/expo/pull/49775)).

## **Expo Observe**

[Expo Observe](https://docs.expo.dev/eas/observe/introduction/) monitors your app in production. It records startup and navigation performance, JavaScript errors, and native crashes from your users' devices, and compares each release with all your releases so you can catch regressions early. In SDK 58, `expo-observe` adds an `errorHandlingEnabled` option to turn off automatic recording of unhandled JavaScript errors ([#48506](https://github.com/expo/expo/pull/48506)) and exposes `Observe.clientId` so you can match Observe data with other tools ([#49599](https://github.com/expo/expo/pull/49599)). `AppMetrics` is deprecated in favor of `Observe`; see [Deprecations](#deprecations).

![The Expo Observe overview dashboard showing active users, sessions, crash-free users, crash-free sessions, and errors, with a release card that compares startup metrics on iOS and Android against all releases and lists the top issues for each platform.](https://cdn.sanity.io/images/9r24npb8/production/b0ad19d6ea59de3f5e86c20bccee4cb21766d5be-2400x1600.jpg)

## **Agentic development with Expo CLIs**

Expo CLI now has updated help text and new commands that work better with agent harnesses. You may see your agent invoking `npx expo command:ps` and `npx expo command:events`, which give it machine-readable information about running Expo processes and their event logs. This helps it understand the state of its own and other Expo dev servers. These commands are experimental. We'll expand them over time and adjust their output to better support automated use of Expo CLI.

We've used this system throughout SDK 58's development, and it has also helped us profile, debug, and improve Expo CLI internally. We've observed that giving agents awareness of all running Expo commands and their events helps them use Expo CLI more reliably and consistently. This replaces our old debug logging, which means you'll see a change in output when you debug Expo CLI yourself with `EXPO_DEBUG=1`.

However, these improvements haven't been enough on their own, so we're also introducing a CLI primarily aimed at agentic development.

### **`@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 that they need 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)). Android widgets also support the `cornerRadius` modifier ([#50333](https://github.com/expo/expo/pull/50333)). 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 available as a preview ([#49823](https://github.com/expo/expo/pull/49823)). 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. To compile the libraries from source instead, set `android.buildExpoModulesCoreFromSource` with [`expo-build-properties`](https://docs.expo.dev/versions/v58.0.0/sdk/build-properties/) ([#50452](https://github.com/expo/expo/pull/50452)).

### 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, Expo Modules 2.0 is in beta on both iOS and Android. The [early look blog post](https://expo.dev/blog/an-early-look-at-expo-modules-2-0) is the best guide until the documentation is available.

## **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/b8eaa36d18d1be9b00369f66496fe3136f9c8146-1800x655.png)

Try it by setting `experiments.noxcturnalTransformWorker` in your app config. It only activates when your project has no custom transform worker and no custom Babel plugins or 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.

- **Loader caching**: loader responses now rely on the platform HTTP cache. Set a `Cache-Control` header in your `loader` to control whether the client reuses cached data. See the [data loaders guide](https://docs.expo.dev/router/web/data-loaders/#caching-and-revalidation) for more information.
- **Server output by default**: Expo Router projects on SDK 58 use `web.output: "server"` when `web.output` is not set, and server output now renders HTML on each request instead of prerendering it during export. To keep the SDK 57 behavior, set `web.output` to `"static"` and enable the new `apiRoutes` option of the `expo-router` config plugin. See [Review server rendering behavior](https://docs.expo.dev/router/migrate/sdk-57-to-58/#review-server-rendering-behavior).
- **Async routes on web by default**: the `expo-router` config plugin now enables [async routes](https://docs.expo.dev/router/web/async-routes/) 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.
- **React transitions**: navigation can now use React transitions to keep the current screen visible while the next one loads and to schedule preloads in the background. By default, only preload operations use transitions. See the [navigation transitions guide](https://docs.expo.dev/router/advanced/navigation-transitions/) to configure when transitions are used.
- **React activities**: 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`](https://docs.expo.dev/router/advanced/react-activity/), to hide inactive content while preserving its state and cleaning up its effects.
- **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://docs.expo.dev/router/error-handling/#error-boundaries-for-screens-in-a-layout), while keeping the navigator mounted.
- **Safe areas on web**: Expo Router no longer provides safe-area insets on web through `react-native-safe-area-context`. Use CSS [`env(safe-area-inset-*)`](https://docs.expo.dev/develop/user-interface/safe-areas/#usage-with-web) values instead.
- **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.
- **Analytics API**: Expo Router now provides an experimental `PerformanceObserver` API for third-party analytics integrations. See the [screen tracking guide](https://docs.expo.dev/router/reference/screen-tracking/#tracking-focused-screens) to learn how to track focused screens.

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` ([#46696](https://github.com/expo/expo/pull/46696)). It connects faster, holds the connection more reliably, and no longer needs `@expo/ngrok`. This is now the default when running `expo start` with a tunnel:

```bash
expo start --tunnel
```

You'll need to be signed in to your Expo account (`expo login`) to use it. You can still use the legacy `@expo/ngrok` tunnels by passing `--tunnel ngrok`.

## **React Native 0.88**

SDK 58 upgrades React Native from 0.86 to 0.88, 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.

## **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/).

## **Launch URLs for development builds and Expo Go**

[Development builds](https://docs.expo.dev/versions/v58.0.0/sdk/dev-client/) and Expo Go now share one launch URL contract. Any query parameter that starts with `__expo_` is a launcher command, on any host, so launch options no longer collide with your app's own deep links ([#50287](https://github.com/expo/expo/pull/50287), [#50288](https://github.com/expo/expo/pull/50288)). The launcher handles these parameters and removes them before your app receives the URL:

- **`__expo_url`**: the URL-encoded project or update URL to load.
- **`__expo_disable_onboarding=1`**: skips the onboarding screen that appears on the first launch after installation.
- **`__expo_disable_fab=1`**: hides the Tools button (the floating button that opens the dev menu) for that launch only.
- **`__expo_disable_auto_launch=1`**: prevents the dev menu from opening when the app starts, for that launch only.

`npx expo start` now prints `{scheme}://?__expo_url={manifestUrl}` instead of `{scheme}://expo-development-client/?url={manifestUrl}`. The legacy form and its parameters keep working, so existing links, QR codes, and scripts are unaffected ([#49651](https://github.com/expo/expo/pull/49651), [#50290](https://github.com/expo/expo/pull/50290)). For CI, end-to-end tests, and agent loops, set `EXPO_NO_DEV_MENU=1` to add the three `__expo_disable_*` parameters to every launch URL and QR code that Expo CLI creates. Expo CLI does this by default when it is not interactive; set `EXPO_NO_DEV_MENU=0` to opt out ([Expo CLI environment variables](https://docs.expo.dev/more/expo-cli/#environment-variables)).

[`expo-linking`](https://docs.expo.dev/versions/v58.0.0/sdk/linking/) and Expo Router ignore the reserved parameters, so they never show up as route search params, and `expo-linking` exports `unwrapDevLaunchURL()` to resolve the URL an app should route from a launch URL. `Linking.parse()` also stops decoding query values twice, so percent-encoded `%`, `+`, and `@` come through unchanged ([#50289](https://github.com/expo/expo/pull/50289)). See [Deep linking to an update's URL](https://docs.expo.dev/develop/development-builds/development-workflows/#deep-linking-to-an-updates-url) for the full list of parameters.

## **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 lock screen 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`**: `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@latest install expo-sqlite` to set it up in your project ([#49867](https://github.com/expo/expo/pull/49867)). Also added `interruptSync()` to cancel running operations on a database connection ([#50123](https://github.com/expo/expo/pull/50123)). To add full-text search (FTS) support on web, use the new `configureWeb()` method to load your own `wa-sqlite` WebAssembly build. [Learn more about `configureWeb()`](https://docs.expo.dev/versions/v58.0.0/sdk/sqlite/#use-a-custom-webassembly-build).
- **`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`**: you can now try a new `expo-location` API, available under `expo-location/next`. It is built around a location provider abstraction, with a simpler position API, position watchers, background location updates, a separate location foreground service on Android, 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)). We'd love to hear your feedback. Keep an eye on the changelog as we continue to backport new features to SDK 58. Separately, geofencing on iOS no longer requires the `location` background mode, which could get apps rejected under App Store guideline 2.5.4 when no feature uses persistent location ([#50197](https://github.com/expo/expo/pull/50197)).
- **`@expo/metro-config`**: inlined `EXPO_PUBLIC_*` environment variables are now recorded in the transform cache, so changing a value invalidates the cached output instead of leaving the old value in your bundle ([#47750](https://github.com/expo/expo/pull/47750)). Stack frames from **node_modules** are no longer collapsed, so an error thrown inside a library shows where it was thrown ([#50973](https://github.com/expo/expo/pull/50973)).
- **`@expo/log-box`**: LogBox now shows the call stack and code frame of an error even when every frame is collapsed, instead of an empty stack ([#50976](https://github.com/expo/expo/pull/50976)).
- **`@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)). A failed `npx expo run:ios` now prints the Xcode build log path and no longer drops Xcode errors from its output ([#48624](https://github.com/expo/expo/pull/48624), [expo/third-party#162](https://github.com/expo/third-party/pull/162)). The terminal now shows the call stack of a thrown error even when all of its frames are collapsed ([#50975](https://github.com/expo/expo/pull/50975)).
- **`expo-updates`**: added the `updates.maxUpdatesToKeep` config to set how many updates are stored on the device. If you use [channel surfing](https://docs.expo.dev/eas-update/channel-surfing/) to switch channels often, a larger value avoids downloading the same updates again each time. [Learn more about `updates.maxUpdatesToKeep`](https://docs.expo.dev/versions/v58.0.0/sdk/updates/#configuration).

## **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-router`**: `withLayoutContext` is deprecated in favor of `integrateWithRouter` ([#50337](https://github.com/expo/expo/pull/50337)).
- **`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)). Passing elements as `List.ForEach` children is deprecated in favor of [`data`, `keyExtractor` and a `children` function](#recycling-lists-for-large-data-sets) ([#49975](https://github.com/expo/expo/pull/49975)). On Android, the `HorizontalCenteredHeroCarousel` `maxItemWidth` prop is deprecated in favor of `preferredItemWidth`, and the five `TimePicker` color names that contain `Unselected` (such as `clockDialUnselectedContentColor`) are deprecated in favor of the Material 3 names without it (such as `clockDialContentColor`) ([#51426](https://github.com/expo/expo/pull/51426)).

## **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 set to be removed after React Native 0.89, 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.
- **macOS**: SDK 58 does not support macOS yet. Support will return when `react-native-macos` is updated to at least React Native 0.86.
- **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**: Expo CLI now sets `NODE_ENV` to `development` or `production` based on the command you run and replaces any other value, so **.env** files and dynamic app configs always load in that mode ([#48554](https://github.com/expo/expo/pull/48554), [#48741](https://github.com/expo/expo/pull/48741)). For example, `NODE_ENV=test npx expo start` now loads **.env.development** instead of **.env.test**. Debug builds use development, and every other build, including custom configurations like `Staging`, uses production ([#49511](https://github.com/expo/expo/pull/49511), [#50661](https://github.com/expo/expo/pull/50661), [#49452](https://github.com/expo/expo/pull/49452), [#49555](https://github.com/expo/expo/pull/49555), [#50204](https://github.com/expo/expo/pull/50204)). On EAS Build, `expo config`, `expo prebuild` and `expo-doctor` use production ([#48938](https://github.com/expo/expo/pull/48938), [#48845](https://github.com/expo/expo/pull/48845)). 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. Router projects now default to [server output](#expo-router-stable-data-loaders-and-native-tabs-improved-core), which renders HTML on each request. 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)). `expo serve` now refuses to start on an export made with `expo export --dev` that includes server code ([#50522](https://github.com/expo/expo/pull/50522)). Export again without `--dev`.

## **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)).
- **Jetpack Compose**: [`@expo/ui`](https://docs.expo.dev/versions/v58.0.0/sdk/ui/jetpack-compose/) and the Expo module template now use Compose UI and Foundation 1.12.1 (from 1.10.6) and Material 3 1.5.0-beta01 (from 1.5.0-alpha17) ([#51426](https://github.com/expo/expo/pull/51426)). There are no breaking changes. A few props are renamed to match Material 3, and the old names still work (see [Deprecations](#deprecations)).

## **Expo Go**

> **Reminder**: The Expo Go app is our tool for getting started quickly; it's an educational tool to help you learn to build on mobile. If you are past that stage and want to build and ship an app, we encourage you to migrate your project to using a [development build](https://docs.expo.dev/develop/development-builds/expo-go-to-dev-build/).

The new Expo Go will be released on the App Store and Google Play within a few weeks. Until then, `npx create-expo-app` creates SDK 57 projects. To start a new SDK 58 project, run `npx create-expo-app --template default@sdk-58` and use a [development build](https://docs.expo.dev/develop/development-builds/introduction/). The new Expo Go will support only SDK 58, so upgrade your project to keep using Expo Go from the stores.

## **Upgrading your app**

Try using our [`expo-upgrade` skill](https://github.com/expo/skills/tree/main/plugins/expo/skills/expo-upgrade) ([installation instructions](https://github.com/expo/skills/tree/main?tab=readme-ov-file#claude-code)) with Claude Code, or a similar tool of your choice, to upgrade your app.

Here's how to upgrade your app to Expo SDK 58 from 57:

- **Upgrade all dependencies to match SDK 58**:

```console
$ $ npx expo install expo@^58.0.0 --fix
```

- **Check for any possible known issues with Expo Doctor**:

```console
$ $ npx expo-doctor@latest
```

- **Refer to the ["Deprecations"](#deprecations) and ["Notable breaking changes"](#notable-breaking-changes) sections** above for breaking changes that are most likely to impact your app.
- **Make sure to check the [changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md) for all other breaking changes!**
- **If you customize AppDelegate.swift or manage the ios directory by hand**: read the [scene life cycle migration guide](https://expo.fyi/ios-scene-lifecycle). See [iOS scene-based life cycle](#notable-breaking-changes).
- **If you use [Continuous Native Generation](https://docs.expo.dev/workflow/continuous-native-generation/)**:
   - Delete the **android** and **ios** directories if you generated them for a previous SDK version in your local project directory. They'll be regenerated the next time you run a build, either with `npx expo run:ios`, `npx expo prebuild`, or with EAS Build.
- **If you <u>don't</u> use [Continuous Native Generation](https://docs.expo.dev/workflow/continuous-native-generation/)**:
   - Run `npx pod-install` if you have an **ios** directory.
   - Apply any relevant changes from the [Native project upgrade helper](https://docs.expo.dev/bare/upgrade/?fromSdk=57&toSdk=58).
   - Optionally, you could consider [adopting prebuild](https://docs.expo.dev/guides/adopting-prebuild/) for easier upgrades in the future.
- **If you use [development builds with expo-dev-client](https://docs.expo.dev/develop/development-builds/introduction/)**: create a new development build after upgrading.
- **If you use Expo Go**: consider migrating to [development builds](https://docs.expo.dev/develop/development-builds/expo-go-to-dev-build/). [Expo Go is not recommended as a development environment for production apps](https://expo.fyi/expo-go-usage).
- **Having trouble?** Refer to the [Troubleshooting your SDK upgrade](https://expo.fyi/troubleshooting-sdk-upgrades) guide.
- **Questions?** Join our weekly office hours on Wednesdays at 12:00 PM Pacific [on Discord](https://chat.expo.dev/).

## **Thanks to everyone who contributed to the release!**

Thanks to [the Expo team](https://expo.dev/about) — everyone contributed one way or another.

Thanks to [_Aziz Becha_](https://github.com/azizbecha), who passed the `expo-hinge` name on npm to us and contributed its Android support ([#51201](https://github.com/expo/expo/pull/51201)).

**External contributors**: [Aaron Leopold](https://github.com/aaronleopold), [Aayush Gautam](https://github.com/L65FREAD), [Adam Kapos](https://github.com/Nezz), [Adam Zvada](https://github.com/zvadaadam), [ahmadaccino](https://github.com/ahmadaccino), [AHMED](https://github.com/ahmdshrif), [Ahmed Sbai](https://github.com/sbaiahmed1), [Albert Martin](https://github.com/Ignigena), [Aldo Ryanda](https://github.com/ryanda9910), [Alec Molloy](https://github.com/alecmolloy), [Alex Rapp](https://github.com/s0uthpaw), [Alexis CHAPPRON](https://github.com/ACHP), [Alfonso Curbelo](https://github.com/alfonsocj), [Alireza Hadjar](https://github.com/AlirezaHadjar), [Alok Debnath](https://github.com/alok-debnath), [Amane INOUE](https://github.com/isaka1022), [Ammar Ahmed](https://github.com/ammarahm-ed), [Anatoliy Magda](https://github.com/aamagda), [Andrea Verrecchia](https://github.com/andreavrr), [Andrei](https://github.com/ferretwithaberet), [Andrzej Wielski](https://github.com/wielski), [Andy Matuschak](https://github.com/andymatuschak), [Aonan Li](https://github.com/aonan-brex), [Aron](https://github.com/likeSo), [Artem](https://github.com/cinques), [Aziz Becha](https://github.com/azizbecha), [Bao Nguyen](https://github.com/giaBaoJS), [Batuhan Demir](https://github.com/batuhandemir98), [Benjamin Komen](https://github.com/benjaminkomen), [Brahmananda Swain](https://github.com/krolyk), [Brian Jeong](https://github.com/bjjeong), [capt-muji](https://github.com/capt-muji), [cdm](https://github.com/conanm), [Changin OH](https://github.com/chang-in), [Charles Burgess](https://github.com/cvburgess), [chinesepowered](https://github.com/chinesepowered), [Christopher Wallace](https://github.com/christopherwxyz), [ciospettw](https://github.com/ciospettw), [ClarityStorm](https://github.com/claritystorm), [Colin McDonnell](https://github.com/colinhacks), [crockalet](https://github.com/crockalet), [Dan Kanefsky](https://github.com/boojamya), [dancer13](https://github.com/dancer1325), [Daniel Avellaneda](https://github.com/davellanedam), [Dave Matthews](https://github.com/debitan), [David](https://github.com/David735453), [David Cornejo](https://github.com/cornejobarraza), [Davide Bertoni](https://github.com/Bert0ns), [Denis LE](https://github.com/ledenis), [Denys Hrychulevych](https://github.com/Den1Marshall), [Devauntae Norman](https://github.com/devauntea), [Dillon Montag](https://github.com/dmontag23), [Dimitris Tzimikas](https://github.com/DimitrisTzimikas), [Dirk Postma](https://github.com/dirkpostma), [Drew Miller](https://github.com/wwdrew), [Duy Anh](https://github.com/duyanhv), [Eddie Xie](https://github.com/oeddyo), [Elehiggle](https://github.com/Elehiggle), [Eliot Gevers](https://github.com/eliotgevers), [Emma Granados](https://github.com/EmmaG2), [enkdevur](https://github.com/gilangabdian), [fallmo](https://github.com/fallmo), [Felipe Castor](https://github.com/felipe-software), [Frederic_Bui](https://github.com/fredericBui), [Gautam Kumar](https://github.com/GautamKumarOffical), [Gauvain](https://github.com/Gauvino), [Gaëtan Kueny](https://github.com/gkueny), [Giovanne Tarcitano](https://github.com/Gitarcitano), [Gregor MacLennan](https://github.com/gmaclennan), [Gregory Moskaliuk](https://github.com/hryhoriiK97), [Hakan Akın](https://github.com/hknakn), [Harry Yu](https://github.com/hsource), [Henrique Barone](https://github.com/henriquegpb), [Henry J](https://github.com/henryj), [Huangshuo Kuang](https://github.com/kkkhs), [Hubert Bieszczad](https://github.com/Brentlok), [Hugo Extrat](https://github.com/huextrat), [huhu415](https://github.com/huhu415), [Ido Yana](https://github.com/idoyana), [Ihor Sviziev](https://github.com/ihor-sviziev), [invivek26](https://github.com/invivek26), [Irfan fandi](https://github.com/irfanfandi), [Jacint Varga](https://github.com/vargajacint), [jakequade-pc](https://github.com/jakequade), [Jakov Glavina](https://github.com/fobos531), [Jakub Hanko](https://github.com/1kuko3), [Janic Duplessis](https://github.com/janicduplessis), [Jason](https://github.com/jzhu1224), [Jason Safaiyeh](https://github.com/safaiyeh), [JB](https://github.com/developwithJB), [jensdev](https://github.com/jensdev), [Jiahao Lu](https://github.com/lujjjh), [Jiun Shin](https://github.com/jiunshinn), [Joao Paulo Costa Marra](https://github.com/jithinlalk25), [Joel Kanzelmeyer](https://github.com/kanzelm3), [Johan Kasperi](https://github.com/johankasperi), [Jonas Rosengren](https://github.com/JoRo-Code), [Jonathan Grimes](https://github.com/jsg2021), [josefnorlin-svt](https://github.com/josefnorlin-svt), [Jozef Harag](https://github.com/Joozty), [K.Dileepa Thushan Peiris](https://github.com/dileepapeiris), [Kamronbek_Juraev](https://github.com/KAMRONBEK), [Kazutoyo Tokai](https://github.com/kazutoyo), [Keven Leone](https://github.com/kevenleone), [Kevin](https://github.com/kmadden84), [Kevin van der Burg](https://github.com/KevinvdBurg), [Kirill Zyusko](https://github.com/kirillzyusko), [Kota](https://github.com/kota113), [Krzysztof Piaskowy](https://github.com/piaskowyk), [Kræn Hansen](https://github.com/kraenhansen), [Kurogoma4D](https://github.com/Kurogoma4D), [Kyle Asaff](https://github.com/KyleAsaff), [Lasya Appali](https://github.com/saisreelasyaappali), [Leonardo Cavalcante](https://github.com/CavalcanteLeo), [Leonardo E. Dominguez](https://github.com/focux), [Lizzi Lindboe](https://github.com/lindboe), [M.M](https://github.com/momomuchu), [Mad Dinh](https://github.com/dennytosp), [Maher Kurdi](https://github.com/Maher-Reven), [MangelSpec](https://github.com/MangelSpec), [Marc Shilling](https://github.com/marcshilling), [Martin Treurnicht](https://github.com/martintreurnicht), [Mateusz Łachacz](https://github.com/blurbyte), [Matthew Chisolm](https://github.com/mchisolm0), [Matthew Lieder](https://github.com/IGx89), [Matthieu Gicquel](https://github.com/matthieugicquel), [Max Karadeniz](https://github.com/mkaradeniz), [Max Lapides](https://github.com/maxlapides), [Maykon Michel Palma](https://github.com/maykonmichel), [Md Asadujjaman Bappi](https://github.com/abappi19), [Michael Chow](https://github.com/chownation), [Michał Pierzchała](https://github.com/thymikee), [Min Hu](https://github.com/minhuwv), [Mina Sameh](https://github.com/gor3a), [misersavingsinc-cpu](https://github.com/misersavingsinc-cpu), [Mitsunao Miyamoto](https://github.com/ramen2020), [mplumador](https://github.com/mplumador), [Mr. Thee](https://github.com/theeket), [MUSE](https://github.com/MUSE-CODE-SPACE), [Nicola Corti](https://github.com/cortinico), [Nikhil Vashistha](https://github.com/NikhilVashistha), [Niklas Grieger](https://github.com/devonik), [Nuno Caseiro](https://github.com/nunocaseiro), [Oleg Bezrukavnikov](https://github.com/OlegBezr), [Olivier Allard](https://github.com/CatLover01), [Oscar Nord](https://github.com/oscnord), [padmeshjakhmola](https://github.com/padmeshjakhmola), [Pieter Willekens](https://github.com/pataar), [pipizhu](https://github.com/debugtheworldbot), [Prabin Silwal](https://github.com/silwalprabin), [Qiyang](https://github.com/qiyangdev), [Radek Czemerys](https://github.com/radko93), [Ramon Claudio](https://github.com/ramonclaudio), [RasmusKard](https://github.com/RasmusKard), [René Klomp](https://github.com/pennersr), [Rio Rafelino](https://github.com/riorafe), [Robert Soriano](https://github.com/wobsoriano), [Rocco Vaccone](https://github.com/rvaccone), [Roitium.](https://github.com/roitium), [Roman Diukachov](https://github.com/enavermate), [Rutvik Nabhoya](https://github.com/rutvik24), [Ryan Lucia](https://github.com/CoffeeFlux), [Ryan Saffer](https://github.com/ryan-saffer), [Samran Asif](https://github.com/webdevsamran), [Samuel Corsan](https://github.com/samuelcorsan), [Samuel Newman](https://github.com/mozzius), [Satyajit Sahoo](https://github.com/satya164), [Sean Bullock](https://github.com/bluespore), [seaxng](https://github.com/seaxng), [sebholl](https://github.com/sebholl), [Self Not Found](https://github.com/wh201906), [Serhii Lizunov](https://github.com/LizunovSergey), [Seydi Charyyev](https://github.com/TheSeydiCharyyev), [Shane Lord](https://github.com/shanelord01), [Shawn Thye](https://github.com/shawnthye-guru), [Shubh Porwal](https://github.com/shubh73), [Simon Eldevig](https://github.com/simoneldevig), [SJvaca30](https://github.com/SJvaca30), [Skylar Barrera](https://github.com/skylarbarrera), [soreavis](https://github.com/soreavis), [Soroh Daukariebi Michael](https://github.com/kariebi), [stareezy](https://github.com/stareezy-1), [Stathis Ntonas](https://github.com/efstathiosntonas), [Stephen Saucier](https://github.com/spsaucier), [Steve South](https://github.com/stevesouth), [stumbaumr](https://github.com/stumbaumr), [stvrmrz](https://github.com/stvrmrz), [Sunny Doshi](https://github.com/doshisunny), [Svend](https://github.com/gee1k), [Taha Koçal](https://github.com/tahakocal), [Tera](https://github.com/0x5bfa), [Thibault Malbranche](https://github.com/Titozzz), [ThomasConway01](https://github.com/ThomasConway01), [Tim](https://github.com/timheilman), [Tim Lenahan](https://github.com/TLenahan), [Tomasz Zawadzki](https://github.com/tomekzaw), [Tomasz Żelawski](https://github.com/tjzel), [Trần Đình Huy](https://github.com/huytdps13400), [tsushanth](https://github.com/tsushanth), [Tuomas Lannes](https://github.com/Lanchez), [Usmanov Samandar](https://github.com/usmsam), [Valentin Nagacevschi](https://github.com/valinagacevschi), [Victor Perez](https://github.com/vicprz), [Vincent Ong](https://github.com/mvincentong), [Vivek JM](https://github.com/vivekjm), [VoulgarisLeoni](https://github.com/VoulgarisLeoni), [xxih](https://github.com/xxih), [yathavan](https://github.com/yathu), [Yousef Abu Shanab](https://github.com/youzarsiph), and [이성현](https://github.com/onlyshyun).

**Beta testers**: [Alexey](https://github.com/wwisheess), [Carlos Espinoza](https://github.com/Carloss616), [Eliot Gevers](https://github.com/eliotgevers), [Frank Manno](https://github.com/frankieshakes), [Godwin Rose Samuel](https://github.com/godwingrs22), [Irek Róg](https://github.com/irekrog), [Jakub Hanko](https://github.com/1kuko3), [Javier Rubio](https://github.com/javirub), [Jon Love](https://github.com/jonnny013), [Jörn Röder](https://github.com/joernroeder), [Kevin Detter](https://github.com/oikalyptus), [Laurent Spitaels](https://github.com/lspitaels), [Liangzhen Zhu](https://github.com/zhuscat), [Marcin Nowak](https://github.com/drnow4u), [marco242424](https://github.com/marco242424), [Matthew Horan](https://github.com/mhoran), [Mike Olson](https://github.com/mwolson), [Moisés Neto](https://github.com/ntocampos), [Nick McMillan](https://github.com/disco-nick), [Nikos](https://github.com/pountzas), [Rúben Ferreira](https://github.com/rubenferreira97), [Taha Koçal](https://github.com/tahakocal), [Thibault Malbranche](https://github.com/Titozzz), [Vincent Guillebaud](https://github.com/vinceglb), and [Yasser's studio](https://github.com/yasserstudio).