CURRENT_SCHEMA_VERSION = 8 (see Schema versions).
This is the published and exported shape. The SDK receives it as the
flow_schema field of a resolve response. You normally never write this by hand; the editor generates it. Read it when you export a flow, bundle one for offline use, or inspect what the SDK actually received.Top level: FlowDefinition
The root object.
| Field | Type | Notes |
|---|---|---|
id | string | Flow ID. |
name | string | Display name. |
version | number | The flow’s content/migration version (1 to 8). Bumped by migrations on load. |
appId | string (optional) | Owning app, for multi-app setups. |
createdAt | string | ISO 8601 timestamp. |
updatedAt | string | ISO 8601 timestamp. |
nodes | FlowNode[] | The graph nodes. See Nodes. |
edges | FlowEdge[] | The graph connections. See Edges. |
entryNodeId | string | ID of the node where the flow starts. |
chrome | GlobalChrome (optional) | Deprecated. Replaced by persistentUI. Kept only so old flows migrate. |
persistentUI | PersistentUI (optional) | Navigation bar, footer, and overlay zones that wrap every screen. See Persistent UI. |
variables | FlowVariable[] (optional) | Flow state. See Variables. |
globalStyles | FlowGlobalStyles (optional) | Theme tokens (colors, typography, spacing, radii, shadows). |
settings | FlowSettings (optional) | Default transitions, localization, analytics provider. |
background | ScreenBackground (optional) | Flow-level default background, inherited by screens. See Backgrounds. |
metadata | Record<string, any> (optional) | Editor/analytics extras. |
Nodes
nodes is a discriminated union keyed on kind. Every node extends a base:
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the flow. |
name | string | Display name. |
kind | FlowNodeKind | One of screen, condition, assign, api, abTest, event, subflow. |
tags | string[] (optional) | Free-form tags. |
metadata | Record<string, any> (optional) | Editor extras. |
ScreenNode (kind: "screen")
The only node kind that renders UI. It holds a component tree.
| Field | Type | Notes |
|---|---|---|
screenType | "standard" | "modal" | "bottomSheet" | "fullScreen" (optional) | Screen presentation style. |
layout | ComponentNode | The root component (a stack, the “Root Stack”). |
props | object (optional) | Screen-level settings. See below. |
enterTransition | TransitionConfig (optional) | Per-screen enter transition override. |
exitTransition | TransitionConfig (optional) | Per-screen exit transition override. |
chromeOverrides | ScreenChromeOverrides (optional) | Deprecated. Use screenSettings. |
screenSettings | ScreenSettings (optional) | Per-screen zone settings. See Zones. |
timeline | ScreenTimelineEvent[] (optional) | Cross-component sequencing. See Animations. |
analytics | { screenKey?, autoTrackImpressions? } (optional) | Per-screen analytics hints. |
ScreenNode.props fields:
| Prop | Type | Notes |
|---|---|---|
background | ScreenBackground | Layered background for this screen. |
backgroundInherit | boolean | When true (or undefined), inherit the flow-level background. |
backgroundColor, gradient | legacy | Kept for backward compatibility during migration. |
padding | number or { top, right, bottom, left } | Screen padding. |
safeArea | boolean | Respect device safe area. |
statusBarStyle | "light" | "dark" | "auto" | Status bar appearance. |
includeInProgress | boolean | Count this screen in auto progress. Defaults to true. |
hideChrome | boolean | Deprecated path; current flows use screenSettings.hideAllZones. |
animationSpeed | number | Global multiplier for all animations on the screen. Default 1.0, range 0.25 to 2.0. |
particleEffect | ScreenParticleEffect | Auto-play particle effect. See Particles. |
ConditionNode (kind: "condition")
If/else branching. Evaluated by the SDK; produces no UI.
| Field | Type | Notes |
|---|---|---|
condition | FlowExpression (string) | A safe-subset expression. See Conditions and expressions. |
outputs | { trueLabel?, falseLabel? } (optional) | Labels for the true/false edges. |
AssignNode (kind: "assign")
Sets variables from expressions. Evaluated by the SDK; produces no UI.
| Field | Type | Notes |
|---|---|---|
assignments | { variableKey: string; expression: FlowExpression }[] | Each entry writes one variable. |
AbTestNode (kind: "abTest")
A schema-level split. Most A/B testing is done with experiments instead.
| Field | Type | Notes |
|---|---|---|
experimentKey | string | Stable ID for analytics. |
variants | { id, label, weight (0-100), targetNodeId }[] | The branches. |
Declared but unsupported nodes
These exist in the type definitions but are not rendered or evaluated by the current iOS or Expo SDKs. Do not rely on them.ApiNode(kind: "api"): a backend/external HTTP call (request,responseMapping,onError).EventNode(kind: "event"): an event-driven entry point (eventType,eventKey).SubflowNode(kind: "subflow"): reuse another flow (subflowId,inputMapping,outputMapping).
Edges (FlowEdge)
Connections between nodes. The editor keeps edges in sync with screen order, so a goNext action follows the default edge to the next screen.
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the flow. |
fromNodeId | string | Source node. |
toNodeId | string | Destination node. |
kind | "normal" | "conditionTrue" | "conditionFalse" | "error" | "event" | "abVariant" (optional) | Edge role. |
label | string (optional) | Display label. |
guard | FlowExpression (optional) | Extra condition for multi-branch nodes. |
transition | TransitionConfig (optional) | Per-edge transition (highest priority in the cascade). |
priority | number (optional) | Ordering hint. |
metadata | Record<string, any> (optional) | Editor extras. |
Components
EachScreenNode.layout is a ComponentNode tree:
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the flow. |
type | ComponentType | One of the 14 kinds. See Component reference. |
props | Record<string, any> (optional) | Untyped prop bag. Resolved per renderer. |
children | ComponentNode[] (optional) | For stacks and other containers. |
bindings | { [propName]: FlowExpression } (optional) | Bind props to expressions. |
interactions | ComponentInteraction[] (optional) | Tap/change/appear handlers. See Actions reference. |
metadata | Record<string, any> (optional) | Editor extras. |
Record<string, any>. The intended shape per component kind is documented in the Component reference.
Persistent UI
persistentUI holds three optional zones that wrap every screen. Full coverage is in Persistent UI zones. The shape:
| Field | Type | Notes |
|---|---|---|
navigationBar | PersistentZone (optional) | Pinned to the top. |
footer | PersistentZone (optional) | Pinned to the bottom. |
overlay | OverlayZone (optional) | Floating layer over content. |
settings.persistDuringTransition | boolean (optional) | Whether zones stay fixed during transitions. Default true. |
Variables
variables is an array of FlowVariable. Full coverage is in Variables. The shape:
| Field | Type | Notes |
|---|---|---|
key | string | Stable key referenced everywhere. |
label | string (optional) | Display name. |
type | "string" | "number" | "boolean" | "list" | Data type. |
listItemType | "string" | "number" | "boolean" (optional) | Required when type is list. |
scope | "global" | v1 supports global only. |
lifecycle | "static" | "session" | Persistence. |
source | { kind: "constant"; value } | { kind: "sdk"; path } | Where the value comes from. |
writable | boolean | Whether actions can change it. |
defaultValue | VariableValue (optional) | Fallback when the source is unavailable. |
Example
A minimal one-screen flow with a single text and a Continue button:Notes
- The SDK decodes leniently. An unknown
ComponentTypedecodes to an internalunknowncase and renders as nothing (or a placeholder in debug builds) rather than failing the whole screen. A single malformed child is skipped, not fatal. chromeandchromeOverridesare deprecated. New flows usepersistentUIandscreenSettings.- The integer
versionhere (the content/migration version, up to 8) is not the same as the wire-formatschema_versionthe SDK checks. See Schema versions.