Building End-to-End iOS Live Activities with Expo and Remote APNs Infrastructure

A stylized smartphone displaying a glowing pill-shaped widget in the Dynamic Island against a dark slate backdrop.

Expo has detailed an architectural design for building end-to-end iOS Live Activities using TypeScript and React Native components without maintaining a separate Xcode project. The approach compiles TSX code into native SwiftUI views via `@expo/ui/swift-ui` and `expo-widgets`, enabling cross-platform apps to leverage Apple's Dynamic Island and Lock Screen widgets for long-running asynchronous tasks.

Client-Side Widget Compilation and Token Management

On the client side, the Live Activity widget UI is defined entirely in React, utilizing a single declarative state structure. Expo's compiler translates the React components into native SwiftUI views, handling the rendering across Lock Screen banners and compact or expanded Dynamic Island layouts. To track activities remotely, devices running iOS 17.2 or higher generate unique, per-activity push tokens rather than relying on standard APNs device tokens.

Because remote activities can be launched via push-to-start when an application is in the background, token registration requires both active component listeners and module-level handlers. This structure ensures that tokens assigned to background-started activities are relayed to the backend immediately.

Backend Event Mapping and APNs Payload Requirements

The backend service maintains database tables correlating active users and specific activity IDs with their corresponding push-to-start and update tokens. When domain events occur, a mapper function transforms raw database updates into the rigid `ContentState` JSON schema expected by the native widget.

Push requests are dispatched over Apple Push Notification service (APNs) using ES256 JWT authentication. The server must send requests to the dedicated `.push-type.liveactivity` topic with specific headers. In APNs payloads, custom properties must be stringified inside a `props` key within the `content-state` object, while initial push-to-start events strictly require an `alert` dictionary alongside explicit attribute identifiers.

AI-generated editorial illustration; not a documentary photograph.

Source: Live Activities with Expo, End to End: Client and Backend

Share this article
FacebookThreadsLinkedInX

Leave a Reply

Your email address will not be published. Required fields are marked *