Migration to v2
Voltra v2 introduces two major architectural changes:
- The old Voltra umbrella package is gone. Voltra now ships as separate iOS, Android, and server packages.
- The native layer moved from Expo Modules to Turbo Modules.
Upgrading to v2 requires updating package installs, Expo plugin configuration, and some API usage. This guide walks through those changes.
Recommended migration order
Section titled “Recommended migration order”- Replace package installs.
- Swap the Expo plugin to the platform-specific package.
- Move JSX imports to
@use-voltra/iosor@use-voltra/android. - Move runtime APIs to the matching
*-clientpackage. - Move server rendering code to
@use-voltra/ios-serveror@use-voltra/android-server. - Rename Android widget APIs that became platform-specific.
- Verify
initialStatePathfiles only import from platform packages.
What changed
Section titled “What changed”- Package split: old
voltra,voltra/client,voltra/server,voltra/android, etc. paths are replaced by scoped packages (@use-voltra/ios,@use-voltra/ios-client,@use-voltra/ios-server,@use-voltra/android,@use-voltra/android-client,@use-voltra/android-server,@use-voltra/server). - Platform-specific JSX namespaces: iOS primitives come from
@use-voltra/iosasVoltra; Android primitives, color tokens, and ongoing notification JSX come from@use-voltra/androidasVoltraAndroid,AndroidDynamicColors, andAndroidOngoingNotification. - Client APIs stay in
*-client: runtime APIs that run inside the React Native app (starting/updating Live Activities, updating or pinning widgets, preview components, event listeners and hooks) come from@use-voltra/ios-clientand@use-voltra/android-client. - Server APIs are platform-specific: use
@use-voltra/ios-serverand@use-voltra/android-serverfor server-side rendering, and@use-voltra/serveronly for cross-platform widget HTTP handlers.
See the sections below for exact import diffs.
Installation changes
Section titled “Installation changes”Install the packages that match the layers you use.
iOS app code
Section titled “iOS app code”npm install @use-voltra/ios @use-voltra/ios-clientyarn add @use-voltra/ios @use-voltra/ios-clientpnpm add @use-voltra/ios @use-voltra/ios-clientbun add @use-voltra/ios @use-voltra/ios-clientAndroid app code
Section titled “Android app code”npm install @use-voltra/android @use-voltra/android-clientyarn add @use-voltra/android @use-voltra/android-clientpnpm add @use-voltra/android @use-voltra/android-clientbun add @use-voltra/android @use-voltra/android-clientOptional server packages
Section titled “Optional server packages”npm install @use-voltra/ios-server @use-voltra/android-server @use-voltra/serveryarn add @use-voltra/ios-server @use-voltra/android-server @use-voltra/serverpnpm add @use-voltra/ios-server @use-voltra/android-server @use-voltra/serverbun add @use-voltra/ios-server @use-voltra/android-server @use-voltra/serverImport mapping
Section titled “Import mapping”iOS app code
Section titled “iOS app code”// v1import { Voltra } from 'voltra'import { startLiveActivity } from 'voltra/client'
// v2import { Voltra } from '@use-voltra/ios'import { startLiveActivity } from '@use-voltra/ios-client'iOS server code
Section titled “iOS server code”// v1import { renderLiveActivityToString, Voltra } from 'voltra/server'
// v2import { Voltra, renderLiveActivityToString } from '@use-voltra/ios-server'Android widget code
Section titled “Android widget code”// v1import { VoltraAndroid } from 'voltra/android'import { updateWidget } from 'voltra/android'
// v2import { VoltraAndroid } from '@use-voltra/android'import { updateAndroidWidget } from '@use-voltra/android-client'Android server widget code
Section titled “Android server widget code”// v1import { createWidgetUpdateNodeHandler } from 'voltra/server'import { AndroidDynamicColors, VoltraAndroid } from 'voltra/android'
// v2import { createAndroidWidgetUpdateNodeHandler } from '@use-voltra/android-server'import { AndroidDynamicColors, VoltraAndroid } from '@use-voltra/android'Expo plugin migration
Section titled “Expo plugin migration”The old docs used a single voltra plugin and nested per-platform config. v2 uses platform-specific plugins.
// v1{ "expo": { "plugins": [ [ "voltra", { "ios": { "groupIdentifier": "group.example.app", "widgets": [] } } ] ] }}
// v2{ "expo": { "plugins": [ [ "@use-voltra/ios-client", { "groupIdentifier": "group.example.app", "widgets": [] } ] ] }}Android
Section titled “Android”// v1{ "expo": { "plugins": [ [ "voltra", { "android": { "widgets": [] } } ] ] }}
// v2{ "expo": { "plugins": [ [ "@use-voltra/android-client", { "widgets": [] } ] ] }}API renames to watch for
Section titled “API renames to watch for”- Android widget updates:
updateWidget(...)->updateAndroidWidget(...) - Android widget reloads:
reloadWidgets(...)for image-preloading remains, but widget refresh APIs usereloadAndroidWidgets(...) - Android widget server handlers:
createWidgetUpdateHandler(...)style examples should becomecreateAndroidWidgetUpdateHandler(...),createAndroidWidgetUpdateNodeHandler(...), orcreateAndroidWidgetUpdateExpressHandler(...) - iOS widget server handlers: use
createIOSWidgetUpdateHandler(...),createIOSWidgetUpdateNodeHandler(...), orcreateIOSWidgetUpdateExpressHandler(...)
Pre-render files
Section titled “Pre-render files”initialStatePath files run in Node during prebuild, not in the React Native runtime.
Use:
@use-voltra/iosfor iOS widget JSX and types@use-voltra/androidfor Android widget JSX and types
Do not import @use-voltra/ios-client or @use-voltra/android-client from pre-render files.
After migrating
Section titled “After migrating”Re-run prebuild for any platform whose plugin configuration changed:
npx expo prebuild --platform iosnpx expo prebuild --platform android