Skip to main content
@capgo/capacitor-live-activities UI & System Open source

Live Activities Capacitor plugin

Manage iOS Live Activities and Dynamic Island layouts from Capacitor with JSON-driven templates

Install

bun add @capgo/capacitor-live-activities bunx cap sync
npm, pnpm or yarn
  • npm install @capgo/capacitor-live-activities
  • pnpm add @capgo/capacitor-live-activities
  • yarn add @capgo/capacitor-live-activities

Guide

How to use Live Activities in Capacitor

Using @capgo/capacitor-live-activities

Capacitor Live Activities Plugin interface for managing iOS Live Activities.

Install

bun add @capgo/capacitor-live-activities
bunx cap sync

iOS Setup

Installing and syncing the plugin does not create the native Live Activity UI. Before calling startActivity, configure ActivityKit in Xcode:

  1. Run bunx cap open ios.
  2. Add a Widget Extension target and enable Include Live Activity.
  3. Set the app and Widget Extension deployment targets to iOS 16.1 or later.
  4. Ensure the extension is embedded in the main app.
  5. Keep an ActivityConfiguration registered in the extension's WidgetBundle, with Lock Screen and all Dynamic Island presentations.
  6. Add NSSupportsLiveActivities to the main app target's Info.plist.
<key>NSSupportsLiveActivities</key>
<true/>

Adding the target alone is not sufficient. The native app or plugin must call ActivityKit's request, update, and end APIs. The Widget Extension must contain SwiftUI code that can decode and render the same ActivityAttributes and content state used by those calls. Include shared ActivityKit models in both the main app and Widget Extension targets. The Xcode-generated Live Activity template does not automatically render the JSON layouts passed to this plugin; the extension also needs a compatible native layout renderer.

Shared Images

When using the image-management methods, add the App Groups capability to the main app and Widget Extension targets. Enable the same group on both targets using the exact identifier expected by the plugin:

group.<MAIN_APP_BUNDLE_ID>.liveactivities

Live Activity extensions cannot access the network. Download remote images in the main app, save them to the shared App Group with saveImage, and then reference the saved image from the layout. Bundled assets must also belong to the Widget Extension target.

Deep Links and Push Updates

  • Register any custom URL scheme used by behavior.widgetUrl or tapUrl under the main app target's Info > URL Types settings.
  • For server-driven updates, add the Push Notifications capability and implement ActivityKit push-token handling with APNs.
  • Add NSSupportsLiveActivitiesFrequentUpdates only when the app requires frequent ActivityKit push updates.

Enabling the Push Notifications capability alone is not sufficient; server-driven updates require native token handling and an APNs backend.

ActivityKit limits the combined static and dynamic Live Activity data to 4 KB. The Dynamic Island is only visible on supported device models; other devices use the Lock Screen presentation.

What This Plugin Exposes

  • areActivitiesSupported - Check if Live Activities are supported on this device. Requires iOS 16.1+ and device support.
  • startActivity - Start a new Live Activity with the specified layout and data.
  • updateActivity - Update an existing Live Activity with new data.
  • endActivity - End a Live Activity.

Example Usage

areActivitiesSupported

Check if Live Activities are supported on this device. Requires iOS 16.1+ and device support.

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

const { supported, reason } = await CapgoLiveActivities.areActivitiesSupported();
if (supported) {
  console.log('Live Activities are supported!');
} else {
  console.log('Not supported:', reason);
}

startActivity

Start a new Live Activity with the specified layout and data.

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

const { activityId } = await CapgoLiveActivities.startActivity({
  layout: {
    type: 'container',
    direction: 'horizontal',
    children: [
      { type: 'text', content: 'Order #{{orderNumber}}', fontSize: 16, fontWeight: 'bold' },
      { type: 'text', content: '{{status}}', fontSize: 14, color: '#666666' }
    ]
  },
  dynamicIslandLayout: {
    expanded: {
      leading: { type: 'image', source: 'sfSymbol', value: 'box.truck' },
      trailing: { type: 'text', content: '{{eta}}' },
      center: { type: 'text', content: '{{status}}' },
      bottom: { type: 'progress', value: 'progress' }
    },
    compactLeading: { type: 'image', source: 'sfSymbol', value: 'box.truck' },
    compactTrailing: { type: 'text', content: '{{eta}}' },
    minimal: { type: 'image', source: 'sfSymbol', value: 'box.truck' }
  },
  data: {
    orderNumber: '12345',
    status: 'On the way',
    eta: '10 min',
    progress: 0.6
  }
});
console.log('Started activity:', activityId);

updateActivity

Update an existing Live Activity with new data.

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

await CapgoLiveActivities.updateActivity({
  activityId: 'abc123',
  data: {
    status: 'Arrived!',
    eta: 'Now',
    progress: 1.0
  },
  alertConfiguration: {
    title: 'Delivery Update',
    body: 'Your order has arrived!'
  }
});

endActivity

End a Live Activity.

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

await CapgoLiveActivities.endActivity({
  activityId: 'abc123',
  data: { status: 'Delivered' },
  dismissalPolicy: 'after',
  dismissAfter: Date.now() + 3600000 // 1 hour from now
});

Full Reference

Keep going from Using @capgo/capacitor-live-activities

If you are using Using @capgo/capacitor-live-activities to plan native media and interface behavior, connect it with @capgo/capacitor-live-activities for the implementation detail in @capgo/capacitor-live-activities, Getting Started for the implementation detail in Getting Started, Using @capgo/capacitor-video-player for the native capability in Using @capgo/capacitor-video-player, @capgo/capacitor-video-player for the implementation detail in @capgo/capacitor-video-player, and Using @capgo/capacitor-native-navigation for the native capability in Using @capgo/capacitor-native-navigation.

FAQ

Live Activities plugin FAQ

How do I install the Live Activities plugin in a Capacitor app?

Run "bun add @capgo/capacitor-live-activities" (or "npm install @capgo/capacitor-live-activities"), then run "bunx cap sync" so the iOS and Android projects pick up the native code. Import it from "@capgo/capacitor-live-activities" in your app code.

Does @capgo/capacitor-live-activities work with React, Vue and Angular?

Yes. Live Activities is a Capacitor package, so it works with any web framework that runs inside Capacitor, including Ionic, React, Vue, Angular, Svelte and plain JavaScript.

Which Capacitor version does @capgo/capacitor-live-activities support?

Capgo plugins follow Capacitor's major version: use the plugin major version that matches your Capacitor major version (for example plugin v8 with Capacitor 8). The compatibility table in the GitHub README lists the maintained versions.

Is @capgo/capacitor-live-activities free and open source?

Yes. The source code is public on GitHub at https://github.com/Cap-go/capacitor-live-activities/ and the package is free to install from npm. Bug reports and pull requests are welcome.

Can I update code that uses Live Activities without an App Store review?

Installing or upgrading the plugin changes native code, so it needs a new store build. After that, JavaScript, HTML and CSS changes that call the plugin can ship instantly with Capgo live updates.

Ship Live Activities changes without waiting for app review

Once the plugin is in your store build, Capgo live updates push your JavaScript, HTML and CSS changes to users in minutes.

Start with Capgo