Reactive UI State

Anything Compose or SwiftUI should re-render on when it changes — a document's flow() gives a UI layer exactly that, with no manual re-reads and no polling.

@Serializable
data class DownloadState(
    val bytesDownloaded: Long = 0,
    val totalBytes: Long = 0,
    val isComplete: Boolean = false,
)

val download = Documents.document<DownloadState>("active-download")

A background worker updates bytesDownloaded as chunks arrive. It's a single field, so update(prop, value) is the natural fit — one direct write to that key:

download.update(DownloadState::bytesDownloaded, bytesSoFar)

A Compose screen collects the same document and redraws on every write, with zero coupling to where the write came from:

@Composable
fun DownloadProgressBar(download: Document<DownloadState>) {
    val state by download.flow().collectAsStateWithLifecycle(initialValue = download.get())
    val progress = state?.let { it.bytesDownloaded.toFloat() / it.totalBytes } ?: 0f

    LinearProgressIndicator(progress = progress)
}

The real sample app demonstrates this exact pattern end to end — a button press writes to a document, and a separate readout re-renders purely by collecting its flow(). See Reactivity for the full flow()/stateFlow() API.