OpenAIExpoMar 4, 2026, 4:30 PM

Home screen widgets and Live Activities in Expo

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

openaienmodel: gpt-5-mini-2025-08-07

Home screen widgets and Live Activities in Expo

Key Points

  • React components for widgets
  • Zero native prebuild setup
  • Live Activities with push updates

Summary

Expo announced expo-widgets (alpha): a library that lets you build iOS home screen widgets and Live Activities using React components and Expo UI with no manual native setup. A config plugin and Continuous Native Generation create the Widget Extension, App Group, and necessary files during prebuild. Widgets are authored as self-contained React components using @expo/ui primitives (e.g. Text, VStack, HStack, Image) which are translated to SwiftUI views at render time.

Key Points

  • Alpha release: expo-widgets removes most native setup required to ship widgets from a React Native app.
  • Render model: widget components run in a separate JS runtime to produce an @expo/ui layout tree; the native side reconstructs the UI with SwiftUI (no React Native rendering at widget render time).
  • Authoring constraints: components must be self-contained, marked with the 'widget' directive, and accept display data via props (including a family size field).
  • Interactivity: widgets can include interactive controls; onPress handlers return partial state updates that are merged and applied without launching the full app.
  • Live Activities: share the same authoring model but target multiple slots (Lock Screen banner, Dynamic Island compact/minimal/expanded); support push updates and push-to-start tokens via APNs.
  • Limitations & next steps: images aren’t supported yet in Expo UI, APIs may change while alpha stabilizes; planned additions include timeline readback and refresh policy options.

Quick usage notes for engineers

  • Minimal widget pattern: mark the component with the 'widget' directive and export with createWidget('Name', Component).
  • Schedule timelines from your app so the system shows the correct entries on schedule; use APNs to update Live Activities remotely.
  • Expect breaking changes during alpha and test thoroughly on device profiles that exercise timelines and Live Activity updates.

Full Translation

Translations

A translation section that keeps the flow of the original article.

openaijamodel: gpt-5-mini-2025-08-07

Expoでのホーム画面ウィジェットとLive Activities

概要

新しい expo-widgets ライブラリにより、ネイティブのセットアップを一切行わずに、Expo UI コンポーネントでホーム画面ウィジェットと Live Activities を構築できます。ホーム画面ウィジェットと Live Activities は、iOS アプリが提供できる最も目立つ機能の一部です。よく作られたウィジェットは、アプリが終了していてもユーザーの生活に常に存在感を与え、ユーザー維持やエンゲージメントを改善します。競争の激しい App Store ではこれはますます重要です。

これまで、React Native アプリからウィジェットを出荷するには多くのネイティブの手続きが必要でした: 別の Xcode ターゲット、データ共有のための App Groups、SwiftUI のレイアウトコード、そして拡張機能をアプリ本体と同期させ続ける負担などです。

本記事では、Expo Widgets(アルファ)を紹介します。これは Expo UI コンポーネントでウィジェットと Live Activities を定義でき、Continuous Native Generation がネイティブ設定を自動で処理してくれる新しいライブラリです。

ウィジェットと Live Activities とは

  • ウィジェットはホーム画面やロック画面に配置される小さな「ひと目で分かる」UI です。システムがスケジュールに沿って描画し、アプリがリアルタイムに描画するわけではありません。ウィジェットからアプリの特定部分へディープリンクできます。
  • iOS 17 以降、ウィジェットはボタンやトグルによるインタラクティブ操作も可能になりました。
  • Live Activities はロック画面や Dynamic Island に表示される時間制限のある更新表示です。配達、試合、乗車などイベント開始時にアプリが開始し、アプリや APNs を介したプッシュで更新します。イベント終了時にアクティビティは終了します。

React への適用

Evan Bacon の expo-apple-targets は Xcode のセットアップを自動化しましたが、それでも SwiftUI でネイティブコンポーネントを書く必要がありました。expo-widgets はウィジェットを React コンポーネントとして定義できるようにします。config plugin が Widget Extension ターゲットを生成し、App Group を設定し、prebuild 時に必要なファイルを作成します。

この仕組みを可能にする鍵は @expo/ui です。ウィジェット拡張はレンダリング時に React Native を動かせないため、システムが要求するタイムラインに応じてネイティブ側で SwiftUI レイアウトに変換できる記述が必要です。@expo/uiTextVStackHStackImage といった React コンポーネントを公開し、これらは SwiftUI のプリミティブに直接対応します。

システムがウィジェットタイムラインを要求すると、あなたのコンポーネントは別の JS ランタイム上で実行されて @expo/ui のレイアウトツリーを生成します。ネイティブ側はその記述を受け取り、SwiftUI ビューを組み立てて UI を再構成します — 実際のレンダリングには React Native は関与しません。

ウィジェット(Widgets)

ウィジェットは通常の React コンポーネントですが、いくつか重要な制約があります:

  • 自己完結している必要がある
  • 関数本体の先頭で "widget" ディレクティブでマークする必要がある
  • 表示データを props として受け取る(さらにウィジェット固有のフィールドがいくつか付与される)

ウィジェットは family のようなフィールドでどのサイズの領域を埋めているかを受け取るため、サイズごとに別ウィジェットを定義せずにレイアウトを調整できます。事前にデータでタイムラインをスケジュールしておけば、システムが適切なエントリを自動的に表示します。

Live Activities

Live Activities は同じ考え方(Expo UI でレイアウトを記述し、props をプッシュして更新)に従いますが、表示されうる「スロット」が複数あります:

  • Lock Screen banner
  • Dynamic Island compact(leading + trailing)
  • Dynamic Island minimal
  • Dynamic Island expanded(leading、center、trailing、bottom)

さらに、サーバーから APNs 経由で直接プッシュ更新を送ることや、push-to-start トークンを使ってユーザーの操作なしにリモートでアクティビティを開始することも可能です。

最初の Widget を作る方法

ライブラリをインストールして最初のウィジェットを設定したら、コーヒーのカウントを追跡し、ホーム画面から直接増やせる最小のウィジェットは次のようになります。

import { Button, Text, VStack } from '@expo/ui/swift-ui';
import { font, foregroundStyle } from '@expo/ui/swift-ui/modifiers';
import { createWidget, WidgetBase } from 'expo-widgets';
type Props = { count: number };
const CoffeeCounter = (p: WidgetBase<Props>) => {
  'widget';
  return (
    <VStack spacing={8}>
      <Text modifiers={[font({ size: 48 })]}></Text>
      <Text modifiers={[font({ size: 32, weight: 'bold' })]}>{p.count}</Text>
      <Button
        modifiers={[foregroundStyle('white')]}
        label="+"
        target="increment"
        onPress={() => ({ count: p.count + 1 })}
      />
    </VStack>
  );
};
export default createWidget('CoffeeCounter', CoffeeCounter);

関数本体の先頭にある "widget" ディレクティブがその関数をウィジェットとしてマークします。onPress は部分的な状態更新を返します — これは現在の状態とマージされて再レンダリングされます。アプリを起動する必要はありません。

ウィジェットと Live Activity のユースケース

  • ウィジェット: 1日のあいだに何度も確認するような情報向け(次のカレンダー予定、現在の天気、タスク数、習慣の継続日数 など)
  • Live Activities: 終了の明確なある進行中イベント向け(配達の ETA カウントダウン、試合のスコアとゲームクロック、フライトステータス、ライドシェアのドライバー位置、ワークアウトタイマー など)

覚えやすいルール: ウィジェットは「チェックイン」向け、Live Activities は「進行中」向け。

今後の予定

今後追加を予定している主な機能:

  • Timeline readback — アプリが閉じている間に適用されたタイムライン更新をアプリ側から取得できる仕組み(アプリロジックへ同期するため)
  • Refresh policy — タイムラインをスケジュールする際、WidgetKit にいつ新しいタイムラインを要求するかを指定するポリシー(たとえば最後のエントリ表示後や特定日時など)
  • Images — 現状の ExpoUI は画像表示をサポートしていません(画像表示のサポートを計画中)

expo-widgets は現在 alpha です。フィードバックを集めて粗さを改善していく中で、いくつかの API が変更される可能性があります。ぜひあなたが作ったものや意見を聞かせてください。動作しない点や機能要望があればお知らせください!