Actions
A tap does one of a small set of things. They compose: any effect can run after another succeeds, and a decision can choose between two.
The set
- Navigation — go to a screen (with params), back, open or close an overlay, select a tab.
- Feedback — show a message: a snackbar, a dialog, or a banner.
- Data — create, update or delete a record; upload a file; call a function; pick an image.
- Account — sign in, sign up, sign out, reset a password, verify a phone.
- State — set, toggle, append, remove, clear (see State).
- Flow — a branch: one bool, two arms.
Chaining
Every effect has an on success. It may be navigation or feedback — or another effect. A workflow is a chain of primitives, at most three deep; each step keeps its own result and its own loading/failed state, and the chain stops at the first failure.
{
"type": "pickImage", "source": "gallery", "result": "picked",
"onSuccess": {
"type": "uploadObject", "bucket": "avatars", "pathPrefix": "users",
"file": {"result": "picked", "field": "localPath"},
"result": "uploaded",
"onSuccess": {
"type": "updateRecord", "collection": "users",
"id": {"from": "route", "path": "user_id"},
"values": {"photo": {"result": "uploaded", "field": "path"}}
}
}
}What is durable
localPath is a file on the device, gone after upload. The thing to save is the storage path the upload returns.Results
An action that produces something — a created record, an uploaded object, a function's response — can name its result. Anything on the same screen can then read it, by field: uploaded.path. A function's response has no declared shape, so its fields can be shown as text but cannot fill a typed property; the checks refuse a guess rather than coerce.
Branching
branch evaluates one boolean — a toggle, a bool state value, a mutation flag — and runs then or else. No expressions, no "truthy" strings; a missing else does nothing. Session routing is the auth gate's job, not a branch's.
{
"type": "branch",
"if": {"from": "app", "path": "seenOnboarding"},
"then": {"type": "navigate", "to": "scr_home"},
"else": {"type": "navigate", "to": "scr_onboarding"}
}