Expo SDK 54 beta is now available
Aug 19, 2025 by

Alan Hughes

Brent Vatne

The SDK 54 beta period begins today and will last approximately two 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 — some of these may include breaking changes.
SDK 54 beta includes React Native 0.81 and React 19.1.0. The full release notes for SDK 54 won't be available until the stable release, but you can browse the changelogs in the expo/expo repository to learn more about the scope of the release and any breaking changes. We'll merge all changelogs into the root CHANGELOG.md when the beta is complete.
We're also hosting office hours on Discord for those of you interested in helping test the release!
Precompiled React Native for iOS
Starting with React Native 0.81 and Expo SDK 54, React Native on iOS and its dependencies will be shipped as precompiled XCFrameworks alongside the source.
We’ve found that [using the precompiled XCFrameworks] reduced clean build times for RNTester from about 120 seconds to 10 seconds (on an M4 Max — exact numbers will vary depending on your machine specs). While you’re unlikely to see a ~10x build time improvement in your app due to the number of other dependencies in most apps that will still need to be compiled, we expect a noticeable reduction in build times in large projects and an even more pronounced improvement in smaller projects where React Native is responsible for a greater share of the build time.
In addition to the speed benefits, this improvement brings us closer to being able to move from CocoaPods to Swift Package Manager for React Native and Expo projects.
Note: in React Native 0.81.0, apps that are compiled in Release using the precompiled XCFrameworks can’t be submitted to the store, but this will be resolved in 0.81.1, which will be available during the week of August 25. In the meantime, if you’d like to submit a build to TestFlight you can disable this behavior with expo-build-properties
by setting ios.buildReactNativeFromSource
to false
.
Learn more in Precompiled React Native for iOS: Faster builds are coming in 0.81.
iOS 26 and Liquid Glass
Support for Liquid Glass icons and Icon Composer
SDK 54 adds support for iOS 26 Liquid Glass icons, which you can create using the new Icon Composer app. The Icon Composer app produces a .icon
file, which you can reference in your app.json under the ios.icon
key:
{"ios": {"icon": "./assets/app.icon"},"android": {"adaptiveIcon": {...}}}
It’s important to note that the Icon Composer app is macOS only — if you don’t have access to a macOS machine that can run the app, then you won’t be able to take advantage of the UI for building the icons. However, the output is relatively straightforward JSON and it’s possible that a tool will emerge to handle this.
When your app using this icon format is run on an older iOS version (iOS ≤ 19), an appropriate fallback will be automatically provided by the operating system.
Liquid Glass Swift UI modifier and button variant
Expo UI for iOS is now in beta, and this includes support for Liquid Glass modifiers and button variants. Documentation coming soon — for now, refer to the examples below and the TypeScript types. Note that you must compile your app with Xcode 26 and run it on iOS 26 in order to use these features. To give it a try, copy and paste the code from this Gist into your app.
See these effects live on this YouTube short. Also notice the iOS 26 bottom tabs UI — this is available in Expo Router v6. See the Expo Router section below for more information.
import { Host, HStack, Text } from "@expo/ui/swift-ui";import { glassEffect, padding } from '@expo/ui/swift-ui/modifiers';// In your component<Host matchContents><HStackalignment='center'modifiers={[padding({all: 16,}),glassEffect({glass: {variant: 'regular',},}),]}><Text>Regular glass effect</Text></HStack></Host>
import { Button, Host, VStack } from "@expo/ui/swift-ui";// In your component<Host matchContents><VStack spacing={8}><Buttonvariant="glassProminent"color="orange"systemImage="questionmark.circle">Help & support</Button><Button variant="glass" systemImage="person">View profile</Button></VStack></Host>
Coming soon during the beta: glass container effects
We’re working on making GlassContainerEffect
available in Expo UI, and we expect this to be ready for testing soon during the beta period.
Xcode 26 beta support available on EAS
You can opt in to using Xcode 26 beta on EAS Build by setting the image
on your build profile to macos-sequoia-15.5-xcode-26.0
. This is required if you plan to take advantage of the above iOS 26 related features.
React Native for Android now targets Android 16 / API 36
Edge-to-edge is now always enabled
With Expo SDK 54 and React Native 0.81 now targeting Android 16, edge-to-edge will be enabled in all Android apps, and cannot be disabled. Additionally, react-native-edge-to-edge
is no longer a dependency of the expo
package because the required functionality was built into React Native by the author of the library, Mathieu Acthernoene. If you are using the react-native-edge-to-edge
config plugin to configure edge-to-edge in your project, make sure that the package is a direct dependency of your project (npx expo install react-native-edge-to-edge
). If you were only using the plugin only to configure the enforceNavigationBarContrast
option you can use the new androidNavigationBar.enforceContrast
property in your app.json to get the same effect without additional dependencies.
Predictive back gesture enabled by default in new projects
The Android predictive back gesture feature is enabled by default on new projects, and disabled by default on existing projects. You can enable or disable the property in your app.json with android.predictiveBackGestureEnabled
. Similar to edge-to-edge, we expect opt-outs will eventually be removed from a future version of Android, and we plan to enable this by default in all projects in SDK 55. Learn more.
Expo Updates & EAS Update
- The HTTP headers Update sends, such as channel, can now be overridden at runtime with
Updates.setUpdateRequestHeadersOverride()
. This enables developers to easily implement patterns such as opting employees into a different update channel than end-users. UnlikeUpdates.setUpdateURLAndRequestHeadersOverride()
, which allows you to also override the update URL and requires thedisableAntiBrickingMeasures
build time flag — the new method only applies to headers, is available without setting any flags, and can be used safely in production apps. Configuration set with either method will apply immediately to the currently running app. This means that you don’t need to restart the app for the new configuration to take effect, you can callUpdates.fetchUpdateAsync()
andUpdates.reloadAsync()
after you update the headers. Learn more about overriding request headers. - The useUpdates() hook now includes a downloadProgress property, which you can use to track the progress of asset downloads during an update. You can use this to show a progress bar when downloading an update, and possibly other creative scenarios. Learn more.
- Updates.reloadAsync() now accepts reloadScreenOptions to give developers control over the UI that is presented while your app is reloading. This provides a much better user experience than a flash of empty content. In development, you can test your reload screen configuration by using
Updates.showReloadScreen({ screenReloadOptions })
andUpdates.hideReloadScreen()
. The following example configuration shows a full screen image and fades out when the update has been applied:
import * as Updates from 'expo-updates';Updates.reloadAsync({reloadScreenOptions: {backgroundColor: '#fa0000',image: require('./assets/images/reload.jpg'),imageResizeMode: 'cover',imageFullScreen: true,fade: true},});
Expo Autolinking now transitively autolinks React Native libraries in the same way as Expo modules
- React Native modules that are installed as transitive dependencies will now be autolinked. While Expo Autolinking always worked this way for Expo modules, now that we take care of linking React Native modules (as of SDK 52) we were able to implement this behavior for React Native modules as well. This means that you will be able to let libraries take care of managing their dependencies, rather than copying and pasting a command to install a handful of native dependencies on their behalf (learn more). You can revert back to the previous autolinking behavior, by adding the
expo.autolinking.legacy_shallowReactNativeLinking: true
flag in your app’s package.json. - Expo and React Native modules will now link according to your app’s direct and nested dependencies, rather than the former behavior of autolinking any module in your node_modules that includes expo-module.config.json. This is primarily relevant to monorepos, where dependencies from multiple apps may be hoisted to the same node_modules directory. Now, either your app or a dependency of your app will need to contain a native module in their
dependencies
orpeerDependencies
for it to be linked. You can revert back to the previous autolinking behavior by adding your node_modules folders toexpo.autolinking.searchPaths
in your app’s package.json. - Expo Autolinking now has unified behavior across Expo and React Native modules, and so it will behave more predictably with isolated dependency installations (Bun and pnpm) and with hoisting conflicts.
Changes that impact how dependencies are handled will often lead to issues in more unique project configurations that couldn’t be anticipated. You can verify your expected native modules against the output of npx expo-modules-autolinking verify -v proactively or to troubleshoot issues if you believe they may be related to these changes. If you need to opt out of both of the changes mentioned above, add the following to your app’s package.json:
{"expo": {"autolinking": {"legacy_shallowReactNativeLinking": true,"searchPaths": ["../../node_modules", "node_modules"]}}}
SDK 54 is the final release to include Legacy Architecture support
In React Native 0.80, the React Native team introduced a code freeze on the Legacy Architecture. In React Native 0.82, it will no longer be possible to opt out of the new architecture. This means that SDK 55, which will likely include React Native 0.83, only support the New Architecture.
In recent months, a growing number of libraries have started to only support the new architecture. For example: react-native-reanimated
v4 and @shopify/flash-list
v2. The interop layer will remain a part of React Native for the foreseeable future, in order to ensure that libraries built for the Legacy Architecture continue to work well in modern apps.
At the time of writing, 75% of SDK 53 projects built on EAS use the New Architecture. If you are still concerned about migrating, learn more about work that has been done to address the last remaining identified issues found while migrating some of the largest React Native apps.
Highlights
- React Native 0.81 with React 19.1. Refer to the release notes for React Native 0.81 and React 19.1 changelog for detailed information. (other info here). Also, learn more about the Expo SDK policy for tracking React Native versions.
- expo-file-system/next is stable: The new expo-file-system API is now stable and exposed as a default. If you were using it prior to upgrading, you will need to update your imports from
expo-file-system/next
→expo-file-system
. The old API is still available underexpo-file-system/legacy
. Some improvements include: an object-oriented API for working with files and directories, support SAF URIs on Android and bundled assets on both iOS and Android. You can expect more information in an upcoming blog post, in the meantime you can refer to the API reference. - expo-sqlite now includes a drop-in implementation for the localStorage web API. If you're already familiar with this API from the web, or you would like to be able to share storage code between web and other platforms, this may be useful. Learn how to import and install the localStorage API.
- Prebuild template now included in the
expo
package rather than downloaded from npm. This ensures that the template used by a givenexpo
package version remains unchanged even if new template versions are released. Updating theexpo
package will also bring in a new template version. Thanks to Thibault Malbranche for suggesting this change. Note that you can still provide a custom prebuild template with the--template
flag. - expo-sqlite added
loadExtensionAsync()
andloadExtensionSync()
APIs to support loading SQLite extensions. The sqlite-vec extension, which supports vector data processing, is also bundled to expo-sqlite as an opt-in extension. You can use sqlite-vec for some RAG AI work. See the implementation in expo#38693, forloadExtensionAsync()
API usage, thewithSQLiteVecExtension
config-plugin option to opt-in sqlite-vec. - expo-app-integrity: New package for verifying app integrity using DeviceCheck (
DCAppAttestService
) on iOS and the Play Integrity API on Android. This allows you to confirm that the app is installed via the App Store or Play Store and is running on a genuine, untampered device. Documentation coming soon. The package is currently named@expo/app-integrity
but we intend to move it toexpo-app-integrity
when we have access to the package. Learn more about the API. - expo/blob: New package for working with binary large objects on iOS and Android. Our implementation is consistent with the W3C specification, providing you with interfaces familiar from the web.
expo-blob
is now in beta, and we’re excited to get your feedback! This library is not yet included in Expo Go. Learn more. - expo-maps: Added support for JSON and Google Cloud based map ID styling on Google Maps and Points of Interest (POI) filtering on Apple maps. Learn more.
- expo-dev-launcher rewrite: we rebuilt the expo-dev-client UI in order to simplify the interface with React Native and improve the Hermes debugging experience. In doing so, we also made some other improvements to the look and feel — let us know what you think!
Apple and Android TV
- Experimental expo-dev-client support for Apple TV, full support on Android TV. Support on tvOS is still early, and you can’t yet authenticate with your Expo account in the app, but give it a try if you have an Apple TV and let us know what you think.
- Added support for Apple TV in various SDK packages: expo-sqlite, expo-background-task, expo-task-manager, expo-insights, expo-image-loader, expo-image-manipulator, and expo-video-thumbnails. See the doc pages for the individual packages for more details.
- tvOS builds will leverage the new precompiled frameworks provided in React Native 0.81: This will significantly reduce build times for these platforms (related blog).
Expo CLI
- Import stack traces are now enabled by default. You can now see a list of imports leading to a missing module which makes it much easier to trace broken packages. With this feature, we found agents (such as claude code) could always resolve broken imports.
experimentalImportSupport
is now enabled by default. We’ve rebuilt Metro import support in Expo CLI to better support React Compiler, and tree shaking. This moves us one step closer to full ESM support in Expo. You can revert to the older system by settingexperimentalImportSupport: false
in the metro.config.js. We plan to remove this flag altogether in the next SDK release. The rebuilt support uses live bindings by default to improve compatibility with a wide range of projects. If you don't want this, setEXPO_UNSTABLE_LIVE_BINDINGS=false
. Note that disabling live bindings might cause issues, especially if import cycles are present in your codebase.- Expo CLI now auto-prefixes CSS by default using the Rust-based
lightningcss
. You can removeautoprefixer
from yourpostcss.config.mjs
file in favor of this implementation. We’ve also added support forbrowserslist
in the package.json. Learn more. @babel/plugin-transform-class-static-block
is now added to babel-preset-expo by default. This enables an even wider set of web and server libraries to work with Expo by default. Learn more about static class blocks.- React Compiler is now enabled in the default template. We recommend using it in your projects. The Meta team is actively fielding support for any remaining issues with React Compiler. You can see which components are memoized by pressing J in Expo CLI and going to the components panel. You will see “Experimental React Compiler is enabled.” printed in your logs when you run
npx expo start
— this is because it is currently in Release Candidate. However, we believe it is ready for most apps. This default may change if this proves false during the beta period. Learn more in the Expo + React Compiler docs. - React Native owner stacks are now enabled by default. These improve errors that occur in React components and make it easier to find/fix problems for both humans and agents.
- Unhandled promise rejections are now logged as errors. After upgrading to this SDK, you might notice new promise rejection errors in your mobile applications. These aren't caused by the SDK itself, but are now properly surfaced as errors, which aligns with how Promises work in web browsers.
- Experimental autolinking resolution was added. Expo CLI is now able to apply Expo Autolinking’s linking decisions to JavaScript module resolution (also known as “sticky resolution”). This prevents mismatches between native modules and JavaScript modules, even in the presence of dependency conflicts and duplicates. Set
EXPO_USE_STICKY_RESOLVER=1
to test this.
Expo Router
- Link now supports iOS view controller previews, transitions, and context menu items. These can be used to add quick actions and information to any link in your app. Learn more.
- Beta support for native tabs on iOS and Android. Unlike the JS tabs implementation, this enables liquid glass tabs, automatic scrolling on tab press, and many other beautiful native effects. The API is still under development and subject to breaking changes until we remove the
unstable-
prefix from the import. Learn more. - Modals on web now emulate iPad and iPhone behavior instead of just being a full screen page with no modal-like attributes.
- New experimental server middleware support. Middleware can be used to run code before requests reach a route. Learn more.
TextDecoderStream
andTextEncoderStream
are added to the native runtime to better support fetch streaming and working with AI.
Deprecations
expo-build-properties
fieldenableProguardInReleaseBuilds
is deprecated in favor ofenableMinifyInReleaseBuilds
.- React Native’s
<SafeAreaView>
component has been deprecated: usereact-native-safe-area-context
instead if you aren’t already. It’s a much more powerful alternative, and one of those libraries that nearly every app uses. - The
notification
configuration field in app config has been deprecated in favor ofexpo-notifications
config plugin.
Notable breaking changes
- First-party JSC support removed from React Native: React Native 0.81 no longer provides built-in JSC support — if you would like to continue using JSC, refer to https://github.com/react-native-community/javascriptcore. Note: this community-maintained JSC library does not yet provide a config plugin, and so you will need to either write your own or modify your native projects directly in order to use it.
- Reanimated v4 introduces react-native-worklets, only supports the New Architecture, and more. Refer to the Reanimated 3.x to 4.x migration guide — but skip modifying your babel.config.js - configuring this will be taken care of for you by babel-preset-expo. If you need to continue using the Legacy Architecture for now, you can continue using v3 — learn more. Additionally, if you use Nativewind then you will need to remain on Reanimated v3 because it does not yet support v4.
- Internal Metro imports have changed in metro@0.83 (the version that is used by React Native 0.81). Importing internal code from any Metro package through
metro/src/..
is not recommended anymore. To emphasize that nested paths are internal, not covered by semver and may change at any point in time, they must now be written asmetro/private/..
instead. For most app developers, this won’t impact you. However, if you are using a library that imports Metro internals, then you may see errors related to Metro import paths — if so, try updating that library to the latest version and post an issue on their GitHub repository if that does not resolve it. - expo-file-system legacy API now available through
expo-file-system/legacy
and the default exports for the library were replaced with what was formerlyexpo-file-system/next
. The quickest way to upgrade and have your app working the same as before is to replace all imports forexpo-file-system
toexpo-file-system/legacy
. Next, you can migrate to the new API at your own pace. If you were already usingexpo-file-system/next
, update your imports toexpo-file-system
instead. Learn more about the new API. - expo-notifications deprecated function exports were removed expo/expo#38782.
Tool version bumps
- Minimum Xcode bumped to 16.1.
- Minimum Node version bumped to 20.19.x.
Known issues
- Hotkeys for reloading and opening the dev menu in iOS 18.4+ simulators not reliably firing. We are investigating the issue. In the meantime, you can use the interactive prompt in Expo CLI to perform both actions and more.
- Expo CLI’s Live Bindings implementation usually prevents require cycles from failing. However, if the entire cycle only consists of default-imports, this will still fail. We are working on a fix for this.
- In React Native 0.81.0, apps that are compiled in Release using the precompiled XCFrameworks can’t be submitted to the store: this will be resolved in 0.81.1, which will be available during the week of August 25. In the meantime, if you’d like to submit a build to TestFlight you can disable this behavior with
expo-build-properties
by settingios.buildReactNativeFromSource
tofalse
. - macOS 26 / Xcode 26 / React Native 0.81.0 / precompiled React Native: this particular combination of tools/configuration will lead to an error during the
pod install
phase. Learn more and how to work around this issue until 0.81.1 is released. - Expo CLI and Expo Tools for VSCode will warn when you provide iOS icons generated from the Icon Composer (.icon). This validation issue will be resolved shortly, and should not interfere with usage.
Known regressions
- Found an issue? Report a regression.
How to try out the beta release
Initialize a new project with SDK 54 beta
# 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
used.
Upgrade an existing project
- Upgrade all dependencies to match SDK 54:
-
npx expo install expo@next --fix
- Install the latest Expo Go for Android emulators/physical devices or iOS simulators:
- Launch your project through Expo CLI (press the a or i keyboard shortcut after running
npx expo start
) and the updated version of Expo Go will be automatically installed.
- Launch your project through Expo CLI (press the a or i keyboard shortcut after running
- Install the latest Expo Go for iOS to your physical device: Join the TestFlight External Beta.
- Read the documentation by selecting it from the version selector in the API reference section.
What to test
- Upgrade your app with
npm install expo@next
oryarn add expo@next
, then runnpx expo install --fix
and consult the Native project upgrade helper and report any issues you encounter. - Build your app with EAS Build, and/or if you have Xcode installed and up to date on your machine and/or Android Studio, try prebuilding your app and running it:
npx expo prebuild --clean
andnpm run ios
andnpm run android
. Alternatively, try outnpx expo run
. Any new issues? Please report them. - Did we miss updating the documentation somewhere? Let us know.
How to report issues
- Create an issue and be sure to fill out the appropriate template (and include a minimal reproducible example).
- Figuring out the underlying causes of issues is always super helpful, and it'll help expedite a solution.
- Let us know that you are using the SDK 54 beta so we can prioritize the issue.
- The most helpful beta testers will be listed in the final release notes (and possibly even provided with some Discord flair — you can link your Discord and GitHub accounts to your Expo account).
Thank you for helping us with testing the release — we look forward to shipping it soon! 🚀