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.

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/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.

Installation changes

Install the packages that match the layers you use.

iOS app code

npm
yarn
pnpm
bun
deno
npm install @use-voltra/ios @use-voltra/ios-client

Android app code

npm
yarn
pnpm
bun
deno
npm install @use-voltra/android @use-voltra/android-client

Optional server packages

npm
yarn
pnpm
bun
deno
npm install @use-voltra/ios-server @use-voltra/android-server @use-voltra/server

Import mapping

iOS app code

// v1
import { Voltra } from 'voltra'
import { startLiveActivity } from 'voltra/client'

// v2
import { Voltra } from '@use-voltra/ios'
import { startLiveActivity } from '@use-voltra/ios-client'

iOS server code

// v1
import { renderLiveActivityToString, Voltra } from 'voltra/server'

// v2
import { Voltra, renderLiveActivityToString } from '@use-voltra/ios-server'

Android widget code

// 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'

Android server widget code

// 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'

Expo plugin migration

The old docs used a single voltra plugin and nested per-platform config. v2 uses platform-specific plugins.

iOS

// v1
{
  "expo": {
    "plugins": [
      [
        "voltra",
        {
          "ios": {
            "groupIdentifier": "group.example.app",
            "widgets": []
          }
        }
      ]
    ]
  }
}

// v2
{
  "expo": {
    "plugins": [
      [
        "@use-voltra/ios-client",
        {
          "groupIdentifier": "group.example.app",
          "widgets": []
        }
      ]
    ]
  }
}

Android

// v1
{
  "expo": {
    "plugins": [
      [
        "voltra",
        {
          "android": {
            "widgets": []
          }
        }
      ]
    ]
  }
}

// v2
{
  "expo": {
    "plugins": [
      [
        "@use-voltra/android-client",
        {
          "widgets": []
        }
      ]
    ]
  }
}

API renames to watch for

  • 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(...)

Pre-render files

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.

After migrating

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

npx expo prebuild --platform ios
npx expo prebuild --platform android

Need React or React Native expertise you can count on?