Skip to content

Widget reactivity: support on-device state changes without a server push #165

@burczu

Description

@burczu

Problem

Voltra's current model resolves everything — colors, sizes, content — on the server into a static
JSON snapshot. The native side is a pure interpreter: it receives the snapshot and displays it.
SwiftUI and Glance both have reactive environment systems, but Voltra bypasses them entirely.

This means the following on-device state changes cannot be reflected in widgets without a new
server push:

  • System appearance (dark/light mode, high contrast, reduced motion)
  • Dynamic Type scale
  • widgetRenderingMode (fullColor / accented / vibrant) — required for Liquid Glass and accented rendering
  • AppIntentConfiguration user parameters (widget gallery configuration, iOS 17+)
  • Time-based changes

The AppIntentConfiguration case is a hard blocker: when a user configures a widget in the gallery,
there is no server push — the extension must render locally with the new parameter. Today, Voltra
has no mechanism for this.

Goal

Enable Voltra widgets to re-render in response to AppIntentConfiguration parameter changes
without a server push and without an app update, while keeping the RN-only developer experience
(no Swift required from the developer).

Constraints

  • Server-driven layout must remain intact where possible — it is Voltra's core value proposition
  • No new native dependencies in the widget extension (no Hermes linking)
  • Developer API stays in JSX + app.json; config plugin generates all Swift boilerplate

Context

The current server-driven JSON model has no mechanism for AppIntent support: when a user
configures a widget in the gallery there is no server push, so the extension has nothing to render
the new parameter value with. Two approaches were evaluated to close this gap:

JSC-in-Extension — a thin JS resolver runs in the extension at render time. Resolves
{{ appIntent.X }} template expressions against current device state, then feeds the resolved
JSON into the existing Swift interpreter. Server retains layout control.

Build-Time Codegen — the Voltra component is compiled to self-contained SwiftUI at build time
by the config plugin. Full native reactivity, zero runtime overhead. Server can push data props
but not layout changes — an app update is required for structural changes.

A complementary branch (poc/widget-reactivity-track-1) addresses rendering improvements that
are independent of AppIntent reactivity: widgetAccentable prop support and light-dark() CSS
Color Level 4 syntax for adaptive text colors. It is a standalone concern that can be merged
separately and is not a prerequisite for either of the above approaches.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions