xFlow demos
The runtime, the substrate, and the flow definitions are all running in this browser tab. Pick a flow, press Run, watch the steps light up. Same definition shape would resolve out of an S3-backed registry on a Fly.io worker, against a Postgres-backed substrate, using the same runtime — that's the point.
Pick a flow
Five flows. One runtime. Every one of them runs in this tab.
The runtime, the substrate, and the registry are all client-side here. No server, no backend — just xFlow's grammar and an in-memory substrate. Click a card to load its definition; press Run to dispatch its actions.
Now playing
E-commerce checkout
Linear flow with retry on charge and a manual review fallback.
Live state
Each step's status, updated in real time as the runtime advances the flow.
Event tail
The last 30 events on this run.
Flow definition
Same JSON that would land in a published registry — exactly what a Next route or a Docker worker would resolve and execute.
{
"id": "shop.checkout",
"version": "1.0.0",
"initial": "load",
"steps": {
"load": {
"id": "load",
"type": "cart.load",
"sideEffects": {
"kind": "idempotent",
"idempotencyRequired": false
}
},
"price": {
"id": "price",
"type": "cart.price",
"sideEffects": {
"kind": "idempotent",
"idempotencyRequired": false
}
},
"charge": {
"id": "charge",
"type": "payments.charge",
"sideEffects": {
"kind": "idempotent",
"idempotencyRequired": false
}
},
"fulfill": {
"id": "fulfill",
"type": "shipping.create",
"sideEffects": {
"kind": "idempotent",
"idempotencyRequired": false
}
},
"review": {
"id": "review",
"type": "human.review",
"sideEffects": {
"kind": "idempotent",
"idempotencyRequired": false
}
}
},
"links": [
{
"when": {
"type": "step.succeeded"
},
"id": "load->price@step.succeeded",
"from": "load",
"to": "price"
},
{
"when": {
"type": "step.failed"
},
"id": "load->review@step.failed",
"from": "load",
"to": "review"
},
{
"when": {
"type": "step.succeeded"
},
"id": "price->charge@step.succeeded",
"from": "price",
"to": "charge"
},
{
"when": {
"type": "step.succeeded"
},
"id": "charge->fulfill@step.succeeded",
"from": "charge",
"to": "fulfill"
},
{
"when": {
"type": "step.failed"
},
"id": "charge->review@step.failed",
"from": "charge",
"to": "review"
}
]
}