Add a Live Activity
Checked against c1b2fa4 on 2026-11-10. The files it covers are unchanged since.
A Live Activity (iOS) or ongoing notification (Android) is an activity
surface. It runs while the surface exists: render it
to start the activity, remove it to end it. examples/timer shows one while
the stopwatch is running or paused.
1. Add the activity
Section titled “1. Add the activity”Wrap it in whatever condition means “something is going on”. In the timer,
that’s {#if active}:
<div class="activity" data-niso-surface="activity"> <div class="row"> <div> <p class="title">{running ? 'Stopwatch' : 'Paused'}</p> {#if running} <time class="big" data-timer-start={origin}>{clock(elapsed)}</time> {:else} <time class="big">{clock(elapsed)}</time> {/if} </div> <div class="actions"> <button onclick={toggle}>{running ? 'Pause' : 'Resume'}</button> <button onclick={lapOrReset}>{running ? 'Lap' : 'Reset'}</button> </div> <p class="count">{laps.length ? 'Lap ' + (laps.length + 1) : ''}</p> </div> <progress value={elapsed % 60000} max="60000" data-timer-start={running ? origin : undefined} data-timer-period={running ? 60000 : undefined}></progress> </div>examples/timer/App.svelte, line 115
The <time data-timer-start> counts by itself, so the activity doesn’t need
an update every second; the page changes the template only when the user
pauses, resumes or laps.
2. Add the Dynamic Island (iOS)
Section titled “2. Add the Dynamic Island (iOS)”The compact and minimal Dynamic Island are three more surfaces:
island.leading, island.trailing and island.minimal. The expanded island
shows island.expanded if the page has one, and otherwise the activity
surface itself.
<div class="island" data-niso-surface="island.leading"><span class="dot on" class:paused={!running}></span></div> <div class="island trailing" data-niso-surface="island.trailing"> {#if running} <time data-timer-start={origin}>{clock(elapsed)}</time> {:else} <time>{clock(elapsed)}</time> {/if} </div> <div class="island minimal" data-niso-surface="island.minimal">examples/timer/App.svelte, line 134
3. Buttons
Section titled “3. Buttons”On Android, the activity’s <button>s become the notification’s actions:
pressing one clicks the button in the page (niso_dom_activate), so the
timer’s Pause and Lap work from the notification. The notification maps
the template onto its fixed slots: the first text is the title, a timer is
its chronometer, a <progress> its progress bar, and the
island.trailing surface’s text the status bar chip. Android 16 promotes it
to a Live Update.
On iOS the Live Activity runs no page, so its buttons are left out.
4. Build
Section titled “4. Build”hosts/apple/build.sh timer # iOS: NSSupportsLiveActivities is in Platforms/ios.plisthosts/android/build.sh timerStart the stopwatch and lock the screen. On iOS nothing appears if the user
has turned Live Activities off for the app: the host checks
areActivitiesEnabled first.