Actions
An object { "type": ..., ...params, "confirm": {...}? }.
Action types
| type | Params | Effect |
|---|---|---|
navigate | endpoint, presentation? | GET a page. Default — push onto the navigation stack (tab bar stays) |
submit | endpoint, method, fields: [id] | field values → JSON body → request |
refresh | — | re-request the current page |
update | — | programmatically refresh data; changed rows update in place |
alert | title, message? | native alert with a single button |
notify | title, message?, status?, haptic? | non-blocking banner HUD, role = status |
open_url | url | system browser |
web_signin | url, callback_scheme?, grant | sign-in via a system web session |
tel / mailto | value | system schemes |
navigate.presentation
| Value | Behavior |
|---|---|
| (none) | push onto the navigation stack, tab bar stays |
sheet | modal sheet (Cancel on the left) — the create/edit pattern |
fullscreen | fullscreen modal without a tab bar; on macOS degrades to a sheet |
submit.method
POST, PATCH, PUT, DELETE. Response: a new page,
{"result":"ok","toast":"...","action":{…}?}, or field errors.
Authorization: grant / revoke
Sign-in and sign-out are ordinary actions that write to an isolated vault. The client never knows the hardcoded token names.
grant (a modifier on submit / web_signin) — take tokens from the response
by JSON paths and put them into the vault:
{
"type": "submit",
"endpoint": "/auth/login",
"fields": [
"u",
"p"
],
"grant": {
"access": "access_token",
"refresh": {
"path": "refresh_token",
"redeem": "/auth/refresh",
"send": {
"in": "body",
"name": "refresh_token"
}
}
}
}
- Path source: the response body (
submit) or the query callback (web_signin). - Local variant:
"grant": { "from": "fields", "access": "{api_key}" }.
revoke (usually on logout) — on 2xx clears the vault:
{ "type": "submit", "endpoint": "/auth/logout", "revoke": true }.
After grant / revoke the client reloads the current page.
execute — an action in the submit response
A successful submit response may carry an action — the client runs it after
submitting (the server decides the next step: alert / notify / navigation / update).
Client reactions on_error / on_success
On any action you can declare how to react, without relying on the server:
{
"type": "submit",
"endpoint": "/save",
"fields": [
"email"
],
"on_error": {
"type": "alert",
"title": "Failed",
"message": "{error.message}"
},
"on_success": {
"type": "notify",
"title": "Done",
"status": "success"
}
}
on_error— on failure (4xx/5xx, except 422 validation).{error.status}and{error.message}(RFC 9457) are available. Not set → toast with the server’s message.on_success— on success, if the server didn’t return its ownaction.- Priority: server
action→on_success→toast.
The confirm modifier
Any action:
"confirm": {
"title": "Delete order?",
"message": "…",
"destructive": true
}
→ a native confirmationDialog / alert before running.
Idempotency
The client sends Idempotency-Key (a UUID per submit). The server must handle
retries with the same key safely.
submit errors
| Response | Behavior |
|---|---|
422 + { "errors": { "comment": "…" } } | field highlighting (form validation) |
| Other 4xx/5xx | human-readable message (toast) |
The primary body format is RFC 9457 (application/problem+json): detail is
taken, otherwise title. Fallback for non-standard APIs — message / error /
toast.