This section documents the context fields recognized by each component type. Fields prefixed _ are private (not inherited by children). Fields without _ are public and inherited down the tree.
Scroll direction: vertical (default) or horizontal.
_showIndicators / showIndicators
bool
Show or hide scroll indicators. Default: true.
_scrollTrigger / scrollTrigger
any / expr
Optional. When set AND style.scroll.anchor is non-nil, the scroll auto-scrolls to the anchor position whenever this value changes. Bind to an expression like {{ count(${messages}) }} so the scroll jumps on new content but not on unrelated state changes (e.g. typing in a text field outside the scroll).
ℹ Make the root a scroll when content can exceed one screen. A module renders into a finite host surface (§4.6, §17.1); content past the fold of a non-scrolling root is clipped and unreachable. Reserve non-scrolling roots for layouts designed to fill exactly one screen.
A scrollable list container that applies platform-native list styling. Children are typically one or more dynamic components. Supports navigation titles/subtitles via style.navigation.
Context key
Type
Description
_isLoading / isLoading
bool / expr
When true, renders _skeletonRows copies of the first child as shimmer rows.
_skeletonRows / skeletonRows
number
Number of skeleton rows shown while loading. Only used when _isLoading is true. Default: 5.
spacer expands to fill available space along the parent stack axis. divider renders a platform-native horizontal rule. Neither requires context fields.
Column and row tracks are configured in style.grid (see §7.23). The lazyVGrid and lazyHGrid variants require columns or rows respectively; omitting them falls back to a single flexible track.
Image source. Accepts sf://, asset://, file://, rs://, and http(s):// schemes (see §6.4).
_placeholder / placeholder
Source string
Optional
Fallback source displayed while the primary source is loading or if it fails. Default: system photo icon.
_contentMode / contentMode
string
Optional
Fill behaviour: fit (default) or fill.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the image. See §15.8.
ℹ Note — image sizing. An image component MUST declare at least one dimension via style.layout — width, height, maxWidth, or maxHeight. Without a frame the image has no target size to fill against, and contentMode: "fill" becomes undefined. The runtime clips rendered content to the declared frame: with fill, overflow on the uncontrolled axis is cropped; with fit, the image is letterboxed within the frame. Frame-less images are rendered zero-sized.
Renders a video player backed by the platform’s media framework (AVKit on Apple). A shimmer skeleton is shown while _isLoading is true. Remote sources begin buffering on appear; if _placeholder is set it is shown as a poster until the first video frame is ready, then faded out.
Context key
Type
Required
Description
_source / source
Source string
REQUIRED
Video URL. Supports https://, http://, file://, rs:// schemes.
_placeholder / placeholder
Source string
Optional
Poster image shown while the video buffers. Replaced by the first frame once the item is ready. Accepts any scheme the image component accepts (see image._source).
_autoplay / autoplay
bool / expr
Optional
Start playback on appear. Default: false.
_loop / loop
bool / expr
Optional
Restart from the beginning when playback ends. Default: false.
Universal media viewer. Inspects the source URL’s file extension (or an explicit _kind hint) and delegates to the appropriate renderer — image, video, or pdf. Use this component when the content type is not known at authoring time or is resolved from state.
Context key
Type
Required
Description
_source / source
Source string
REQUIRED
Any media URL.
_kind / kind
string
Optional
Content-type hint. One of: auto (default), image, video, pdf. Overrides auto-detect.
_placeholder / placeholder
Source string
Optional
Poster shown for images / unknown types on load failure, and for video while the item buffers.
_contentMode / contentMode
string
Optional
fit (default) or fill — image rendering only.
_autoplay / autoplay
bool / expr
Optional
(video) Start playback on appear. Default: false.
_loop / loop
bool / expr
Optional
(video) Loop when playback ends. Default: false.
_muted / muted
bool / expr
Optional
(video) Mute audio. Default: false.
_page / page
number / expr
Optional
(pdf) Initial page (1-indexed). Default: 1.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of content.
Auto-detection extension map:
Extension
Detected kind
jpg, jpeg, png, gif, webp, heic, bmp, tiff
image
mp4, mov, m4v, avi, mkv, m3u8
video
pdf
pdf
sf:// or asset:// source (any extension)
image
Unrecognised or absent
unknown → placeholder
Style: style.video and style.pdf keys are forwarded to the respective renderer. style.common and style.layout apply to the outer container.
Renders a platform-native progress indicator. When _value and _total are present, renders as a determinate bar. Omit both for an indeterminate spinner.
Context key
Type
Required
Description
_value / value
number / expr
Optional
Current progress value.
_total / total
number / expr
Optional
Maximum value. When provided alongside _value, renders a determinate bar. Default: 1.0.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the progress indicator. See §15.8.
Renders an interactive map. Map children define custom annotation content rendered at the pin location. Visual presentation (standard / hybrid / imagery) is configured via style.map (see §7.19).
Context key
Type
Required
Description
_region / region
object
Conditional
Center coordinate for the annotation pin. Only relevant when the component has children.
_position / position
object / expr
REQUIRED
Two-way state binding for the camera position. Shape: { "region": { center: {latitude, longitude}, span: {lat, lon} } }.
_name / name
string / expr
Optional
Annotation label shown at the pin. Annotation is suppressed when the component has no children.
_debounce / debounce
number (sec)
Optional
Debounce delay in seconds before region-change events fire.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the map. See §15.8.
The _format context key on a text component transforms the numeric value of _text into a human-readable string using locale-aware formatting. It is a single-key object: the key selects the formatter kind (date, number, or duration).
ℹ Note: _text MUST resolve to a numeric value when _format is present. For date and duration formatters the value is seconds since Unix epoch. Use #{now} for the current time.
⚠ Anti-pattern. A bare-string _format value is silently ignored by the runtime — the raw numeric value renders unformatted (e.g. 1779434773.6742659 instead of "Yesterday"). The wrapper key is mandatory.
If _text references a stored timestamp (@{item.ts}, ${entry.ts}) without a valid _format wrapper, treat it as a bug — the user sees the raw Unix epoch double.
Renders a text input field. Set _isSecured: true to switch to masked password input (SecureField). Binds its value to a state key via _text.
Context key
Type
Required
Description
_label / label
string
REQUIRED
Placeholder / accessibility label text.
_text / text
state ref
REQUIRED
Two-way binding to a state key. Example: ”${email}”.
_focused / focused
bool / expr
Optional
Controls input focus.
_debounce / debounce
number (sec)
Optional
Delays onChange events. 0 disables debounce.
_keyboard / keyboard
number
Optional
Keyboard type hint integer.
_isSecured / isSecured
bool
Optional
When true, renders as a masked password input. Default: false.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the field. See §15.8.
ℹ Keyboard dismissal. Numeric keyboards (decimalPad, numberPad, phonePad) have no Return key. Wrap numeric textfields in a scroll and set style.scroll.dismissesKeyboard (see §7.16) to let the user dismiss by scrolling. Alphanumeric keyboards additionally support the Return key (see style.textField.submitLabel).
A value picker. The presentation style is controlled by style.picker (see §7.20). Defaults to the platform-native automatic style when style.picker is absent.
Context key
Type
Required
Description
_label / label
string
Optional
Picker accessibility label.
_selection / selection
state ref
REQUIRED
Two-way binding to the selected value.
_options / options
array / expr
REQUIRED
Array of selectable values.
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the picker. See §15.8.
Two-way binding to a numeric state key. The slider writes a continuous double in [0, 1].
_isLoading / isLoading
bool / expr
Optional
Show shimmer skeleton instead of the slider. See §15.8.
ℹ Slider is a normalised 0..1 input by design. The component does not declare or accept _min / _max / _step — those are author concerns, not runtime concerns. Scale, label, and discretise the raw 0..1 value wherever you consume it. This keeps the slider primitive small and pushes domain semantics to the author per §11.1.
Discrete integer scale (e.g. “1-10 severity”, “1-5 stars”). Prefer a picker with style.picker: "segmented" or "wheel" and explicit string _options — the binding is naturally discrete and the picker label IS the value.
Continuous-feel slider with a scaled integer display. Bind _value to a 0..1 state key; scale and cast at the consumer side (display label, repository write, history row):
Wraps content in a navigable stack. Set the navigation bar title using style.navigation.navigationTitle, or by setting navigationTitle as a public context key on the child component.
A tappable row that pushes a destination module onto the navigation stack. The link’s children define the row’s visual content.
Field
Type
Required
Description
destination
module
REQUIRED
The component to push. MUST be of type module. Set style.navigation.navigationTitle on it to set the pushed screen title.
ℹ The destination MUST have "type": "module". The runtime always treats the destination as a module regardless of the declared "type". Placing a plain layout component (scroll, vstack, etc.) directly as the destination renders but its events (in particular onAppear) will not fire. Wrap your destination layout in { "type": "module", "state": {…}, "events": {…}, "children": [ <your-layout> ] }.
Scope: context is inherited; state is NOT shared. The destination module inherits the link’s per-item context (e.g. inside a dynamic prototype, @{item} from the outer dynamic is available in the destination module’s events.onAppear actions and in child expressions). State, however, is a fresh scope bound to the destination’s own state block — ${someKey} inside the destination resolves against the destination module’s own state, not the parent module’s. A child module cannot directly read parent state keys. It may indirectly update a parent’s state key only via name-matched upward propagation — i.e. if the child declares a state key of the same name and updates its own key, the parent’s matching-name key is also updated (see §11.3). The child cannot address the parent’s state by name directly.
Threading data into a pushed destination therefore has two patterns:
Pass values through @{item} context (read-only, frozen at push time). Works for primitives or whole arrays — e.g. if each row object already contains the sub-list to show in the detail, _data: "@{item.children}" inside the destination’s dynamic just works.
Let the destination re-fetch via a repo action in its own onAppear, using @{item.<id>} to parameterise the request. This is the pattern the weather example uses.
There is no built-in mechanism to read an outer module’s state keys from a pushed destination. If the detail needs live, two-way-synced data with the parent, restructure the parent’s state so the per-row data is carried inside each row (Pattern 1) or avoid the link/destination split and render the detail inline in the same module via conditional state.
Builds a tab-bar application layout. Each direct child SHOULD be a module. Set the following keys in each child module’s context to configure its tab bar entry.
Child module context key
Type
Description
_tabTitle / tabTitle
string
Label shown in the tab bar.
_tabImage / tabImage
Source string
Icon shown in the tab bar. A bare system-icon name (no scheme prefix) is accepted as shorthand for sf://<name> — see §6.4.
_tabBadge / tabBadge
number / expr
Integer badge count shown on the tab icon. Omit or set to 0 to hide badge.
A two- or three-column iPad layout using NavigationSplitView. On compact-width devices (iPhone, Slide Over) it collapses gracefully to a single-column stack. Children are positional:
ℹ Note: State ownership and propagation. Each module owns its declared state keys exclusively. A state action always applies a local merge gated by the dispatching module’s declarations (unmatched keys are dropped from the local write). It then does one of two things: a chain-less write also propagates upward by name match to any ancestor that has declared a same-named key (the dispatching module does NOT need to declare the key); a write with an output.successchain stays local and the chain runs in the dispatching module’s context to preserve ${...} / @{item} scope — there is no propagation. Parent modules cannot write to child-module state; sibling modules cannot write to each other’s state; and no module can read another module’s state — state reads are strictly scoped to the module that declares the key.
ℹ Note — Render surface & overflow. A module’s root render tree is laid out into a host-provided surface of finite size — the area the host allocates for the module, below its own chrome (back button, title bar, tabs). The surface is a hard boundary: a conforming runtime MUST contain the module within it (§17.1), so an oversized root is clipped to the surface and can never overdraw host chrome or intercept touches outside it. Because clipping cuts content rather than revealing it, author the root to fit the surface: when a screen’s content can exceed the viewport — long forms, dynamic lists, anything that grows with state — make the root, or the region that overflows, a scroll (§4.1). A non-scrolling root (e.g. a vstack with spacers) is only for layouts meant to fill exactly one screen; size their primary content responsively (maxWidth / maxHeight: "infinity", ratios) rather than fixed width / height in points, so they still fit smaller viewports and larger Dynamic Type.
A non-visual proxy that renders a component pulled from the dependency registry by its source. A template instance MAY supply additional context keys that override or parameterize the referenced component.
Context key
Type
Required
Description
_source / source
Source string
REQUIRED
Location of the component. Use dp://id for registered dependencies, or file://path for a packaged JSON component file.
_inline / inline
boolean
Optional
When true, the component is immediately initialized. Default: true.
Renders a prototype component repeatedly for each element in an array data source. Injects item (the current element) and index (zero-based position) into the prototype’s context.
Field
Type
Required
Description
context._data / context.data
array / expr
REQUIRED
Array value or state ref. Example: ”${items}“.
prototype
component
REQUIRED
Component rendered once per item. Access item data with @{item.field} and @{index}.
context._isLoading / isLoading
bool / expr
Optional
When true, renders _skeletonRows copies of the prototype with "isLoading": true injected, so each primitive inside shows its own skeleton.
context._skeletonRows
number
Optional
Number of prototype skeleton rows to show while loading. Only used when _isLoading is true. Default: 5.
Renders one of two component branches based on a boolean condition. The un-rendered branch is not instantiated.
Context key
Type
Required
Description
_condition / condition
bool / expr
REQUIRED
Boolean or expression selecting the branch.
_trueComponent / trueComponent
component
REQUIRED
Rendered when condition is truthy.
_falseComponent / falseComponent
component
Optional
Rendered when condition is falsy. If omitted, nothing is rendered. Use { "type": "empty" } for an explicit no-op branch. Omitting this field produces a validation warning.