### Build and Run Example App
Source: https://github.com/callstackincubator/voltra/blob/main/CONTRIBUTING.md
Commands to build the plugin, install example dependencies, prebuild for iOS, and run the example app on iOS.
```sh
# 1) Build the plugin
npm run build:plugin
# 2) Install example dependencies
(cd example && npm install)
# 3) Prebuild for iOS
(cd example && npx expo prebuild -p ios)
# 4) Run on iOS
(cd example && npx expo run:ios)
```
--------------------------------
### Install Dependencies
Source: https://github.com/callstackincubator/voltra/blob/main/CONTRIBUTING.md
Run this command to install all required project dependencies.
```bash
npm install
```
--------------------------------
### Receive Push-to-Start Tokens for Remote Launch
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/server-side-updates.md
Implement this listener to get tokens for starting Live Activities remotely. Send these tokens to your server to initiate new Live Activities via push notifications.
```tsx
useEffect(() => {
const subscription = addVoltraListener('activityPushToStartTokenReceived', ({ pushToStartToken, type }) => {
// Send the token to your server for starting new Live Activities
sendTokenToServer({
token: pushToStartToken,
type: 'start',
})
})
return () => {
subscription.remove()
}
}, [])
```
--------------------------------
### Example Custom Preview Layout XML
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/api/plugin-configuration.md
An example of an XML layout file that can be used for custom widget previews.
```xml
```
--------------------------------
### Install Voltra Client Packages
Source: https://github.com/callstackincubator/voltra/blob/main/README.md
Install the client package for each platform you need. This is a prerequisite for setting up Voltra.
```sh
# iOS
npm install @use-voltra/ios-client
# Android
npm install @use-voltra/android-client
```
--------------------------------
### Install iOS Packages
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/getting-started/installation.mdx
Use this command to install the necessary packages for iOS Live Activities and widgets.
```bash
npm install @use-voltra/ios @use-voltra/ios-client
```
--------------------------------
### Start Live Activity with Multiple Configuration Options
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/api/configuration.md
Combine various configuration options, including dismissalPolicy, staleDate, and relevanceScore, when starting a Live Activity for comprehensive control.
```typescript
await startLiveActivity(variants, {
dismissalPolicy: { after: 30 },
staleDate: Date.now() + 2 * 60 * 60 * 1000, // 2 hours
relevanceScore: 0.7,
})
```
--------------------------------
### Install Android Packages
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/getting-started/installation.mdx
Use this command to install the necessary packages for Android Home Screen widgets and ongoing notifications.
```bash
npm install @use-voltra/android @use-voltra/android-client
```
--------------------------------
### Starting a Live Activity
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/managing-live-activities-locally.md
Use `startLiveActivity()` to create and display a new Live Activity with initial content and configuration.
```APIDOC
## startLiveActivity()
### Description
Creates and displays a new Live Activity.
### Method
`startLiveActivity(variants, options)`
### Parameters
- `variants` (LiveActivityVariants) - Defines the UI for different display contexts (lockScreen, compact, minimal, expanded).
- `options` (object) - Configuration options:
- `activityName` (string, Optional) - For re-binding on app restart.
- `deepLinkUrl` (string, Optional) - URL to open when tapped.
- `channelId` (string, Optional) - Broadcast channel (iOS 18+).
- `dismissalPolicy` (object, Optional) - Policy for dismissing the activity (e.g., `{ after: seconds }`).
- `staleDate` (Date, Optional) - The date when the activity becomes stale.
- `relevanceScore` (number, Optional) - A score indicating the relevance of the activity.
### Returns
- `Promise` - A promise that resolves to the Live Activity ID.
```
--------------------------------
### Install @use-voltra/metro
Source: https://github.com/callstackincubator/voltra/blob/main/packages/metro/README.md
Install the package using npm. This is typically done when you need to customize the Metro configuration directly.
```sh
npm install @use-voltra/metro
```
--------------------------------
### Install Voltra Android Client Package
Source: https://github.com/callstackincubator/voltra/blob/main/packages/android-client/README.md
Install the Android client package using npm.
```sh
npm install @use-voltra/android-client
```
--------------------------------
### Install @use-voltra/compiler
Source: https://github.com/callstackincubator/voltra/blob/main/packages/compiler/README.md
Install the compiler package directly if you need to build custom tooling on top of Voltra's source scanner.
```bash
npm install @use-voltra/compiler
```
--------------------------------
### Install Voltra CLI
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/getting-started/react-native-cli.mdx
Install the Voltra CLI as a dev dependency.
```bash
npm install --save-dev voltra
```
--------------------------------
### Starting Live Activities
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/managing-live-activities-locally.md
Use `startLiveActivity()` to create and display a new Live Activity with specified UI variants and configuration options.
```APIDOC
## startLiveActivity()
### Description
Creates and displays a new Live Activity.
### Parameters
#### variants
- **variants** (LiveActivityVariants) - Required - Defines the UI for different display contexts (lockScreen, compact, minimal, expanded).
#### options
- **options** (object) - Optional - Configuration options for the Live Activity.
- **activityName** (string) - Optional - For re-binding on app restart.
- **deepLinkUrl** (string) - Optional - URL to open when tapped.
- **channelId** (string) - Optional - Broadcast channel (iOS 18+).
- **dismissalPolicy** (object) - Optional - Policy for automatic dismissal.
- **after** (number) - Optional - Dismiss after a specified number of seconds.
- **staleDate** (number) - Optional - Timestamp for when the activity becomes stale.
- **relevanceScore** (number) - Optional - Score indicating the activity's relevance.
### Returns
- **Promise** - A promise that resolves to the Live Activity ID.
```
--------------------------------
### Install Voltra iOS Client
Source: https://github.com/callstackincubator/voltra/blob/main/packages/ios-client/README.md
Install the iOS client package using npm. This command is essential for adding Voltra's iOS capabilities to your project.
```sh
npm install @use-voltra/ios-client
```
--------------------------------
### Install Optional Server Packages for Voltra v2
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/getting-started/migration-v2.mdx
Install optional server-side packages for Voltra v2 to handle iOS and Android specific server logic, as well as general server functionalities.
```bash
npm install @use-voltra/ios-server @use-voltra/android-server @use-voltra/server
```
--------------------------------
### Start Live Activity with Deep Link
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/interactions.md
Configure the deep link URL when starting a Live Activity. This allows your app to be launched via a deep link when the Live Activity itself is tapped.
```typescript
import { useLiveActivity } from 'voltra/client'
const { start } = useLiveActivity(
{
lockScreen: ,
},
{
activityName: 'activity-detail',
deepLinkUrl: '/voltraui/activity-detail',
}
)
```
--------------------------------
### Install Voltra Package
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/getting-started/installation.mdx
Use this command to add Voltra to your Expo project. This is the primary step for integrating Voltra.
```bash
npm install voltra
# or
yarn add voltra
# or
pnpm add voltra
```
--------------------------------
### Button Usage Example
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/components/interactive.md
Demonstrates how to create and use a Voltra Button. Buttons fire interaction events that can be handled in your app. Requires iOS 17.0+.
```tsx
Play Music
```
```typescript
import { addVoltraListener } from 'voltra/client'
const subscription = addVoltraListener('interaction', (event) => {
if (event.identifier === 'play-button') {
// Handle play action
}
})
```
--------------------------------
### Get Active Widgets on iOS
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/developing-widgets.md
Fetches a list of widgets currently installed on the user's home screen. Useful for understanding which widgets are active and their configurations.
```typescript
import { getActiveWidgets } from '@use-voltra/ios-client'
const widgets = await getActiveWidgets()
// [{ name: 'weather', family: 'systemSmall', kind: '...' }]
```
--------------------------------
### Get Active Widgets
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/developing-widgets.md
Use this API to detect which widgets are currently installed on the user's home screen. Refer to 'Querying Active Widgets' for more details.
```typescript
import { getActiveWidgets } from 'voltra/client'
const widgets = await getActiveWidgets()
// [{ name: 'weather', family: 'systemSmall', kind: '...' }]
```
--------------------------------
### Create Notification Channel with Expo Notifications
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/managing-ongoing-notifications.md
Use `expo-notifications` to create a notification channel, which is required before starting an ongoing notification. This example creates a channel named 'delivery_updates'.
```typescript
import * as Notifications from 'expo-notifications'
await Notifications.setNotificationChannelAsync('delivery_updates', {
name: 'Delivery updates',
importance: Notifications.AndroidImportance.DEFAULT,
})
```
--------------------------------
### Start Live Activity with Stale Date
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/api/configuration.md
Set a staleDate to automatically dismiss the Live Activity after a specified time. This example sets the stale date to one hour from the current time.
```typescript
import { startLiveActivity } from 'voltra/client'
// Dismiss the Live Activity after 1 hour
await startLiveActivity(variants, {
staleDate: Date.now() + 60 * 60 * 1000, // 1 hour from now
})
```
--------------------------------
### Build Plugins
Source: https://github.com/callstackincubator/voltra/blob/main/CONTRIBUTING.md
Execute this command to build all project plugins.
```bash
npm run build:plugin
```
--------------------------------
### Get Active Widgets - TypeScript
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/querying-active-widgets.md
Use this function to retrieve an array of active widget configurations. It logs the count and details of each installed widget. Note that iOS may cache widget configurations, leading to a slight delay in data.
```typescript
import { getActiveWidgets } from '@use-voltra/ios-client'
async function checkWidgets() {
const activeWidgets = await getActiveWidgets()
console.log(`User has ${activeWidgets.length} widgets installed`)
activeWidgets.forEach(widget => {
console.log(`- Widget Name: ${widget.name}`)
console.log(` Family: ${widget.family}`)
console.log(` Kind: ${widget.kind}`)
})
}
```
--------------------------------
### Start or Update Notification with upsertAndroidOngoingNotification
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/managing-ongoing-notifications.md
Use `upsertAndroidOngoingNotification` to either start a new ongoing notification or update an existing one with a single call. This is useful for scenarios where the same flow might be re-entered, simplifying logic compared to separate start and update calls. It returns an object indicating whether the notification was 'started' or 'updated'.
```typescript
import {
AndroidOngoingNotification,
upsertAndroidOngoingNotification,
} from 'voltra/android/client'
const result = await upsertAndroidOngoingNotification(
,
{
notificationId: 'workout-1',
channelId: 'fitness_updates',
}
)
if (result.ok) {
console.log(result.action) // 'started' or 'updated'
}
```
--------------------------------
### Basic Styling with VStack and Text
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/styling.md
Demonstrates applying basic styles like padding, background color, border radius, font size, and color to Voltra components using the `style` prop.
```tsx
import { Voltra } from 'voltra'
const element = (
Styled Text
)
```
--------------------------------
### Run Prebuild Command
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/custom-fonts.md
After configuring the fonts, run `npx expo prebuild` to copy the font files to the correct Android asset directory.
```bash
npx expo prebuild
```
--------------------------------
### Start a Live Activity
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/managing-live-activities-locally.md
Initiates and displays a new Live Activity. Requires defining UI variants for different contexts and can include optional configuration like activity name, deep link, and dismissal policies.
```typescript
import { startLiveActivity } from 'voltra/client'
import { Voltra } from 'voltra'
const variants = {
lockScreen: (
Order Confirmed
Your order is being prepared
),
// Define compact, minimal, and expanded variants for Dynamic Island
compact: Order confirmed,
minimal: ,
expanded: (
Order Confirmed
Your order is being prepared
),
}
const activityId = await startLiveActivity(variants, {
activityName: 'order-123', // Optional: for re-binding on app restart
deepLinkUrl: 'myapp://order/123', // Optional: URL to open when tapped
channelId: 'CTrNsYq/Ee8AALLzHQaVlA==', // Optional: broadcast channel (iOS 18+)
dismissalPolicy: { after: 30 },
staleDate: Date.now() + 60 * 60 * 1000, // 1 hour
relevanceScore: 0.8,
})
```
--------------------------------
### Create a "Hello World" Live Activity
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/setup.mdx
This component demonstrates how to start a simple Live Activity using Voltra. The JSX is automatically converted to SwiftUI for native display.
```tsx
import React from 'react'
import { startLiveActivity } from 'voltra/client'
import { Voltra } from 'voltra'
function HelloWorldActivity() {
const activityUI = (
Hello World from Voltra!
Your first live activity
)
const startActivity = async () => {
await startLiveActivity({
lockScreen: activityUI,
})
}
return (
Start Live Activity
)
}
```
--------------------------------
### Implement Widget Initial State
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/widget-pre-rendering.md
Create a file at the specified `initialStatePath` that exports a `WidgetVariants` object, defining the initial UI for different widget families.
```tsx
import { Voltra, type WidgetVariants } from 'voltra'
const initialState: WidgetVariants = {
systemSmall: Content,
systemMedium: Content,
systemLarge: Content,
}
export default initialState
```
--------------------------------
### Start a Live Activity
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/managing-live-activities-locally.md
Use `startLiveActivity` to create and display a new Live Activity with defined UI variants and configuration options. It returns the activity ID.
```typescript
import { Voltra } from '@use-voltra/ios'
import { startLiveActivity } from '@use-voltra/ios-client'
const variants = {
lockScreen: (
Order Confirmed
Your order is being prepared
),
// Define compact, minimal, and expanded variants for Dynamic Island
compact: Order confirmed,
minimal: ,
expanded: (
Order Confirmed
Your order is being prepared
),
}
const activityId = await startLiveActivity(variants, {
activityName: 'order-123', // Optional: for re-binding on app restart
deepLinkUrl: 'myapp://order/123', // Optional: URL to open when tapped
channelId: 'CTrNsYq/Ee8AALLzHQaVlA==', // Optional: broadcast channel (iOS 18+)
dismissalPolicy: { after: 30 },
staleDate: Date.now() + 60 * 60 * 1000, // 1 hour
relevanceScore: 0.8,
})
```
--------------------------------
### Toggle Example
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/components/interactive.md
Example of a Voltra Toggle component, which fires an interaction event when its state changes. It supports a default value. Requires iOS 17.0+.
```tsx
```
```typescript
import { addVoltraListener } from 'voltra/client'
const subscription = addVoltraListener('interaction', (event) => {
if (event.identifier === 'notifications-toggle') {
// Handle toggle state change
}
})
```
--------------------------------
### Handling Live Activity Interactions with Voltra
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/interactions.md
Use this example to set up interactive buttons and toggles in your Live Activity and listen for interaction events. Ensure you handle state updates manually after an interaction.
```typescript
import { useEffect } from 'react'
import { useLiveActivity } from 'voltra/client'
import { Voltra } from 'voltra'
import { addVoltraListener } from 'voltra/client'
function MyLiveActivity() {
const { start, update } = useLiveActivity(
{
lockScreen: (
Music Player
Play
Pause
),
},
{
activityName: 'music-player',
deepLinkUrl: '/music-player',
}
)
useEffect(() => {
const subscription = addVoltraListener('interaction', (event) => {
switch (event.identifier) {
case 'play-button':
// Start playback
console.log('Play button tapped')
break
case 'pause-button':
// Pause playback
console.log('Pause button tapped')
break
case 'shuffle-toggle':
// Toggle shuffle mode
console.log('Shuffle toggled')
break
}
})
return () => subscription.remove()
}, [])
return null
}
```
--------------------------------
### Start or Update Ongoing Notification
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/managing-ongoing-notifications.md
The `upsertAndroidOngoingNotification` function allows you to start a new ongoing notification or update an existing one with a single call. This is particularly useful for scenarios where the same flow might be re-entered, simplifying logic compared to separate start and update calls. It's also beneficial for remote updates via push notifications.
```APIDOC
## upsertAndroidOngoingNotification
### Description
Starts a new ongoing notification or updates an existing one. Useful for simplifying logic when re-entering flows or for remote updates.
### Method Signature
`upsertAndroidOngoingNotification(notificationContent: AndroidOngoingNotification, options: { notificationId: string, channelId: string })`
### Parameters
#### Notification Content
- **notificationContent** (AndroidOngoingNotification.Progress | AndroidOngoingNotification.Media | AndroidOngoingNotification.Default) - Required - The content of the ongoing notification.
#### Options
- **notificationId** (string) - Required - A unique identifier for the notification.
- **channelId** (string) - Required - The ID of the notification channel to use.
### Request Example
```tsx
import {
AndroidOngoingNotification,
upsertAndroidOngoingNotification,
} from 'voltra/android/client'
const result = await upsertAndroidOngoingNotification(
,
{
notificationId: 'workout-1',
channelId: 'fitness_updates',
}
)
if (result.ok) {
console.log(result.action) // 'started' or 'updated'
}
```
### Response
- **ok** (boolean) - Indicates if the operation was successful.
- **action** (string) - Returns 'started' if a new notification was created, or 'updated' if an existing one was modified.
```
--------------------------------
### Configure Widget Pre-rendering
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/api/plugin-configuration.md
Use `initialStatePath` to specify the path to a pre-rendered widget state file. This file will be bundled and used for immediate display before dynamic updates.
```json
{
"widgets": [
{
"id": "weather",
"displayName": "Weather Widget",
"targetCellWidth": 2,
"targetCellHeight": 2,
"initialStatePath": "./widgets/weather-initial.tsx"
}
]
}
```
--------------------------------
### Configure Initial State for Server-Driven Widgets
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/server-driven-widgets.md
Define the `initialStatePath` in the widget configuration to provide a pre-rendered default state. This content is displayed until the first server fetch completes, ensuring a meaningful initial display.
```json
{
"id": "dynamic_weather",
"displayName": "Dynamic Weather",
"description": "Weather with live server updates",
"targetCellWidth": 2,
"targetCellHeight": 1,
"initialStatePath": "./widgets/android/weather-initial.tsx",
"serverUpdate": {
"url": "https://api.example.com/widgets/render",
"intervalMinutes": 60
}
}
```
--------------------------------
### Swift Payload Migration Example
Source: https://github.com/callstackincubator/voltra/blob/main/CONTRIBUTING.md
Example of a Swift migration struct for payload schema versioning. Increment `currentVersion` and implement `VoltraPayloadMigration` to handle schema changes and ensure forward compatibility.
```swift
// Example: V1ToV2Migration.swift
struct V1ToV2Migration: VoltraPayloadMigration {
static let fromVersion = 1
static let toVersion = 2
static func migrate(_ json: JSONValue) throws -> JSONValue {
// Transform v1 payload to v2 format
// Update the version field
var result = json
result["v"] = .int(2)
return result
}
}
// In VoltraPayloadMigrator.swift:
private static let migrations: [Int: any VoltraPayloadMigration.Type] = [
1: V1ToV2Migration.self,
]
```
--------------------------------
### APNS Payload for Starting a Live Activity (iOS 17.2+)
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/server-side-updates.md
This payload is used for starting a Live Activity remotely on iOS 17.2 and later. It includes `attributes-type`, `attributes`, and an `alert` object.
```json
{
"aps": {
"event": "start",
"content-state": {
"uiJsonData": "{\"lockScreen\":{\"type\":\"VStack\",\"children\":{\"type\":\"Text\",\"children\":\"Hello\",\"props\":{}}},\"props\":{}}" },
"attributes-type": "VoltraAttributes",
"attributes": {
"name": "some-name",
"deepLinkUrl": "app://some-deep-link-url"
},
"timestamp": 1764145755,
"alert": {
"title": "Driver arrived",
"body": "Ready for pickup"
}
}
}
```
--------------------------------
### Implement Initial Widget State
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/android/development/widget-pre-rendering.md
Create a file at the specified `initialStatePath` that exports a default Voltra component using `VoltraAndroid` primitives for the initial UI.
```tsx
import { VoltraAndroid } from '@use-voltra/android'
const InitialWeatherWidget = (
Loading weather...
)
export default InitialWeatherWidget
```
--------------------------------
### Start Android Big Text Notification
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/development/managing-ongoing-notifications.md
Starts an ongoing notification with a large text content on Android. Requires a notification ID and channel ID. This is useful for displaying more detailed information.
```typescript
import {
AndroidOngoingNotification,
startAndroidOngoingNotification,
} from 'voltra/android/client'
await startAndroidOngoingNotification(
,
{
notificationId: 'match-42',
channelId: 'sports_updates',
}
)
```
--------------------------------
### Configure Greeting Widget in app.json
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/configurable-widgets.md
This JSON configuration sets up the 'greeting_widget' as a Dynamic Widget. It specifies the entry point, display information, and defines a user-editable 'label' parameter with a default value of 'Hello'.
```json
{
"expo": {
"plugins": [
[
"@use-voltra/ios-client",
{
"widgets": [
{
"id": "greeting_widget",
"entry": "./widgets/ios/greeting-widget.tsx",
"displayName": "Greeting Widget",
"description": "A Dynamic Widget with user-editable parameters",
"supportedFamilies": ["systemSmall", "systemMedium"],
"initialStatePath": "./widgets/ios/greeting-widget.tsx",
"appIntent": {
"parameters": [
{
"name": "label",
"title": "Label",
"default": "Hello"
}
]
}
}
]
}
]
]
}
}
```
--------------------------------
### Start or Update Android Ongoing Notification
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/android/development/managing-ongoing-notifications.md
Use `upsertAndroidOngoingNotification` to either start a new ongoing notification or update an existing one with a single call. This is useful for scenarios where an app might re-enter the same flow multiple times, simplifying logic compared to separate start and update calls. It's particularly effective for remote updates via push notifications.
```typescript
import { AndroidOngoingNotification } from '@use-voltra/android'
import {
upsertAndroidOngoingNotification,
} from '@use-voltra/android-client'
const result = await upsertAndroidOngoingNotification(
,
{
notificationId: 'workout-1',
channelId: 'fitness_updates',
}
)
if (result.ok) {
console.log(result.action) // 'started' or 'updated'
}
```
--------------------------------
### Provide Initial Widget State
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/server-driven-widgets.md
Specify a path to a pre-rendered default state for your widget. This content is displayed before the first server fetch completes, improving user experience.
```json
{
"id": "dynamic_weather",
"displayName": "Dynamic Weather",
"description": "Weather with live server updates",
"supportedFamilies": ["systemSmall", "systemMedium"],
"initialStatePath": "./widgets/ios/weather-initial.tsx",
"serverUpdate": {
"url": "https://api.example.com/widgets/render",
"intervalMinutes": 30
}
}
```
--------------------------------
### Live Activity Configuration Options
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/managing-live-activities-locally.md
Configure the behavior, lifecycle, and appearance of Live Activities using various options.
```APIDOC
## Configuration Options
### Description
Voltra provides several configuration options to control Live Activity behavior, lifecycle, and appearance. These options can be used with `startLiveActivity()`, `updateLiveActivity()`, and `stopLiveActivity()`.
### Dismissal Policy
Controls how Live Activities behave after they end.
**Options:**
- `'immediate'` (default): Live Activity is dismissed immediately when it ends.
- `{ after: number }`: Live Activity remains visible for the specified number of seconds after ending, then automatically dismisses.
**Examples:**
```typescript
// Immediate dismissal (default)
await startLiveActivity(variants, {
dismissalPolicy: 'immediate',
})
// Keep visible for 30 seconds after ending
await startLiveActivity(variants, {
dismissalPolicy: { after: 30 },
})
// Update dismissal timing for active Live Activities
await updateLiveActivity(activityId, variants, {
dismissalPolicy: { after: 300 }, // 5 minutes
})
// Set dismissal timing when stopping
await stopLiveActivity(activityId, {
dismissalPolicy: { after: 10 },
})
```
### Stale Date
Specifies when a Live Activity should be considered stale and automatically dismissed by iOS.
**Example:**
```typescript
// Dismiss after 1 hour
await startLiveActivity(variants, {
staleDate: Date.now() + 60 * 60 * 1000,
})
// Dismiss after 2 hours
await startLiveActivity(variants, {
staleDate: Date.now() + 2 * 60 * 60 * 1000,
})
```
**Note:** If you provide a `staleDate` in the past, it will be ignored.
### Relevance Score
Helps iOS prioritize which Live Activities to display when space is limited.
**Range:** 0.0 to 1.0 (default: 0.0)
**Examples:**
```typescript
// High priority (e.g., active delivery)
await startLiveActivity(variants, {
relevanceScore: 0.8,
})
// Low priority (e.g., background task)
await startLiveActivity(variants, {
relevanceScore: 0.2,
})
```
### Channel ID (broadcast push, iOS 18+)
Subscribes the Live Activity to a broadcast channel for server-side updates. When provided, the activity receives updates via broadcast push notifications instead of individual device tokens—one server notification updates all activities on that channel.
**Example:**
```typescript
// For shared content (e.g., live sports, flight status)
await startLiveActivity(variants, {
activityName: 'match-123',
channelId: 'CTrNsYq/Ee8AALLzHQaVlA==', // From APNs channel management
})
```
**Requirements:** Requires `enablePushNotifications: true` in the Voltra plugin and the Broadcast Capability enabled in your Apple Developer account. See [Server-side updates](./server-side-updates.md#broadcast-push-notifications-ios-18) for details.
```
--------------------------------
### Configure Widget Initial State Path
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/widget-pre-rendering.md
Add `initialStatePath` to your widget configuration in `app.json` to specify the file for pre-rendering the widget's initial state.
```json
{
"expo": {
"plugins": [
[
"@use-voltra/ios-client",
{
"widgets": [
{
"id": "weather",
"displayName": "Weather Widget",
"description": "Shows current weather conditions",
"supportedFamilies": ["systemSmall", "systemMedium", "systemLarge"],
"initialStatePath": "./widgets/weather-initial.tsx"
}
]
}
]
]
}
}
```
--------------------------------
### Start Live Activity with Channel ID (TypeScript)
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/server-side-updates.md
Use this function to start a Live Activity and subscribe it to a broadcast channel. This is for iOS 18+; older versions will fall back to token-based updates.
```typescript
import { startLiveActivity } from 'voltra/client'
import { Voltra } from 'voltra'
const activityId = await startLiveActivity(variants, {
activityName: 'match-123',
channelId: 'CTrNsYq/Ee8AALLzHQaVlA==', // Channel ID from your server
})
```
--------------------------------
### Voltra Android Client Quick Example
Source: https://github.com/callstackincubator/voltra/blob/main/packages/android-client/README.md
A React Native component and function to display weather information in a Voltra Android widget and update it. This example uses Voltra's Box, Column, and Text components for layout and styling.
```tsx
import { updateAndroidWidget, VoltraAndroid } from '@use-voltra/android-client'
const WeatherWidget = ({ temperature, condition }: { temperature: number; condition: string }) => (
{temperature}°C
{condition}
)
export async function refreshWeatherWidget() {
await updateAndroidWidget('my_widget', )
}
```
--------------------------------
### Configure Widget Initial State Path
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/development/widget-pre-rendering.md
Add `initialStatePath` to your widget configuration in `app.json` to specify the location of the initial state file.
```json
{
"expo": {
"plugins": [
[
"voltra",
{
"widgets": [
{
"id": "weather",
"displayName": "Weather Widget",
"description": "Shows current weather conditions",
"supportedFamilies": ["systemSmall", "systemMedium", "systemLarge"],
"initialStatePath": "./widgets/weather-initial.tsx"
}
]
}
]
]
}
}
```
--------------------------------
### AreaMark Example
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/android/charts.md
Use AreaMark to quickly visualize overall volume or rise/fall patterns. Supports interpolation.
```tsx
```
--------------------------------
### Live Activity with Interactive Elements
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/development/interactions.md
Use this example to create a Live Activity with buttons and toggles. Ensure you handle interaction events asynchronously using `addVoltraListener`. Requires iOS 17.0+ for interactivity.
```typescript
import {
useEffect
} from 'react'
import { Voltra } from '@use-voltra/ios'
import { useLiveActivity } from '@use-voltra/ios-client'
import { addVoltraListener } from '@use-voltra/ios-client'
function MyLiveActivity() {
const { start, update } = useLiveActivity(
{
lockScreen: (
Music Player
Play
Pause
),
},
{
activityName: 'music-player',
deepLinkUrl: '/music-player',
}
)
useEffect(() => {
const subscription = addVoltraListener('interaction', (event) => {
switch (event.identifier) {
case 'play-button':
// Start playback
console.log('Play button tapped')
break
case 'pause-button':
// Pause playback
console.log('Pause button tapped')
break
case 'shuffle-toggle':
// Toggle shuffle mode
console.log('Shuffle toggled')
break
}
})
return () => subscription.remove()
}, [])
return null
}
```
--------------------------------
### Create a 'Hello World' Live Activity with Voltra
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v2/ios/setup.mdx
This component demonstrates how to create a simple Live Activity using Voltra's JSX components. The `startLiveActivity` function is used to display the UI on the lock screen.
```tsx
import React from 'react'
import { Voltra } from '@use-voltra/ios'
import { startLiveActivity } from '@use-voltra/ios-client'
function HelloWorldActivity() {
const activityUI = (
Hello World from Voltra!
Your first live activity
)
const startActivity = async () => {
await startLiveActivity({
lockScreen: activityUI,
})
}
return (
Start Live Activity
)
}
```
--------------------------------
### AreaMark Example
Source: https://github.com/callstackincubator/voltra/blob/main/website/docs/v1/ios/charts.md
Use AreaMark to visualize overall volume or rise/fall patterns. Supports custom color and interpolation.
```tsx
```