Skip to main content

Integrate Airborne in Expo

This guide integrates Airborne into an Expo app and ships an over-the-air release. The native wiring differs from bare React Native (Expo wraps the host and delegate), but the CLI workflow and the release steps are the same. If you're on bare React Native, use Integrate Airborne in React Native.

Expo requires native access

Airborne boots before React Native, so it integrates at the native layer. You need a project with native directories — use expo prebuild (or the bare workflow / a development build). It does not work with Expo Go.

Prerequisites

  • An Expo app with native projects generated (expo prebuild).
  • Node.js + npm, the Android toolchain (JDK + Android SDK), and the iOS toolchain (Xcode + CocoaPods).
  • An Airborne organisation, application, and access token.

Step 1 — Install the SDK

npx expo install airborne-react-native
# or: npm install airborne-react-native@^0.37.0
cd ios && pod install && cd ..

Add the Airborne Maven repository to android/build.gradle (or settings.gradle):

maven { url "https://maven.juspay.in/jp-build-packages/hyper-sdk/" }

Step 2 — Wire up the native side (Expo specifics)

Expo apps wrap React Native's activity delegate and host, so the Airborne wiring uses Expo's wrappers:

  • Android — wrap AirborneReactActivityDelegate in ReactActivityDelegateWrapper, and AirborneReactNativeHost in ReactNativeHostWrapper, with the JS main module set to .expo/.virtual-metro-entry. Full walkthrough: Expo Android setup.
  • iOS — your AppDelegate extends ExpoAppDelegate; you initialize Airborne and, importantly, only update the didFinishLaunchingWithOptions method (Expo has three application functions). Full walkthrough: Expo iOS setup.

The Airborne instance still points at your release config URL with a matching namespace:

airborneInstance = Airborne(
this.applicationContext,
"https://airborne.juspay.in/release/<organisation-name>/<application-name>",
object : AirborneInterface() {
override fun getNamespace(): String = "<application-name>"
// getDimensions(), onEvent(), startApp(indexPath) — see the Expo Android setup page
}
)
tip

Pass -e / --expo to create-local-airborne-config (next step) so the CLI generates Expo-aware config.

Step 3 — Set up your project with the CLI

Authenticate and scaffold, marking the project as Expo:

npx airborne-devkit login --client_id <client-id> --client_secret <client-secret>
npx airborne-devkit create-local-airborne-config --expo
npx airborne-devkit create-local-release-config -p android
npx airborne-devkit create-remote-files -p android --upload -t "v1.0.0"
npx airborne-devkit create-remote-package -p android -t "v1.0.0"

See Local configuration and Remote files & packages.

Step 4 — Create a release in the dashboard

Open Releases → Create Release. Configure the timeouts, leave targeting empty for your first release (it goes to everyone), and select the package you just cut:

Step 1 — Configure the boot and release-config timeouts.Step 1 — Configure the boot and release-config timeouts.
Step 1 — Configure the boot and release-config timeouts.
Step 4 — pick the package version to ship.Step 4 — pick the package version to ship.
Step 4 — pick the package version to ship.

Confirm the generated config:

Confirm the release config before creating it.Confirm the release config before creating it.
Confirm the release config before creating it.

The wizard's other steps (targeting, remote config, file priorities, resources) are covered in Dashboard → Releases.

Step 5 — Verify and roll out

Watch the release and confirm the device booted from the downloaded bundle:

The release detail page — status, traffic, and rollout progress.The release detail page — status, traffic, and rollout progress.
The release detail page — status, traffic, and rollout progress.
import { getBundlePath } from 'airborne-react-native';

const path = await getBundlePath('<application-name>');
console.log('Booted from', path);

Troubleshooting and the lifecycle event sequence: Verify the integration and the events reference.

Next steps