Skip to content

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.

  1. Replace package installs.
  2. Swap the Expo plugin to the platform-specific package.
  3. Move JSX imports to @use-voltra/ios or @use-voltra/android.
  4. Move runtime APIs to the matching *-client package.
  5. Move server rendering code to @use-voltra/ios-server or @use-voltra/android-server.
  6. Rename Android widget APIs that became platform-specific.
  7. Verify initialStatePath files only import from platform packages.
  • 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/ios as Voltra; Android primitives, color tokens, and ongoing notification JSX come from @use-voltra/android as VoltraAndroid, AndroidDynamicColors, and AndroidOngoingNotification.
  • 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-client and @use-voltra/android-client.
  • Server APIs are platform-specific: use @use-voltra/ios-server and @use-voltra/android-server for server-side rendering, and @use-voltra/server only for cross-platform widget HTTP handlers.

See the sections below for exact import diffs.

Install the packages that match the layers you use.

Terminal window
npm install @use-voltra/ios @use-voltra/ios-client
Terminal window
npm install @use-voltra/android @use-voltra/android-client
Terminal window
npm install @use-voltra/ios-server @use-voltra/android-server @use-voltra/server
// v1
import { Voltra } from 'voltra'
import { startLiveActivity } from 'voltra/client'
// v2
import { Voltra } from '@use-voltra/ios'
import { startLiveActivity } from '@use-voltra/ios-client'
// v1
import { renderLiveActivityToString, Voltra } from 'voltra/server'
// v2
import { Voltra, renderLiveActivityToString } from '@use-voltra/ios-server'
// v1
import { VoltraAndroid } from 'voltra/android'
import { updateWidget } from 'voltra/android'
// v2
import { VoltraAndroid } from '@use-voltra/android'
import { updateAndroidWidget } from '@use-voltra/android-client'
// v1
import { createWidgetUpdateNodeHandler } from 'voltra/server'
import { AndroidDynamicColors, VoltraAndroid } from 'voltra/android'
// v2
import { createAndroidWidgetUpdateNodeHandler } from '@use-voltra/android-server'
import { AndroidDynamicColors, VoltraAndroid } from '@use-voltra/android'

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": []
}
]
]
}
}
// v1
{
"expo": {
"plugins": [
[
"voltra",
{
"android": {
"widgets": []
}
}
]
]
}
}
// v2
{
"expo": {
"plugins": [
[
"@use-voltra/android-client",
{
"widgets": []
}
]
]
}
}
  • Android widget updates: updateWidget(...) -> updateAndroidWidget(...)
  • Android widget reloads: reloadWidgets(...) for image-preloading remains, but widget refresh APIs use reloadAndroidWidgets(...)
  • Android widget server handlers: createWidgetUpdateHandler(...) style examples should become createAndroidWidgetUpdateHandler(...), createAndroidWidgetUpdateNodeHandler(...), or createAndroidWidgetUpdateExpressHandler(...)
  • iOS widget server handlers: use createIOSWidgetUpdateHandler(...), createIOSWidgetUpdateNodeHandler(...), or createIOSWidgetUpdateExpressHandler(...)

initialStatePath files run in Node during prebuild, not in the React Native runtime.

Use:

  • @use-voltra/ios for iOS widget JSX and types
  • @use-voltra/android for Android widget JSX and types

Do not import @use-voltra/ios-client or @use-voltra/android-client from pre-render files.

Re-run prebuild for any platform whose plugin configuration changed:

Terminal window
npx expo prebuild --platform ios
npx expo prebuild --platform android