Declare the rules. Orb builds the app, or tells you why it can't.
curl -fsSL https://orb.almadar.io/install.sh | shCheckout
on Order · states: 3 · transitions: 3orb compiles the same .lolo to each of these.
There is no SHIP out of pending.
Checkout
on Order · states: 3 · transitions: 41app std-orb-sample-checkout "1.0.0"
2"std-orb-sample-checkout — the checkout program shown on orb.almadar.io's home page, running: an order that cannot ship before it is paid. The page shows this file as code beside the running trait, and each move is reported (MOVED) so its state machine can follow along."
3orbital Orders {
4 entity Order [runtime] {
5 id : string!
6 total : number
7 }
8
9 trait Checkout -> Order [interaction, instance] {
10 initial: pending
11
12 state pending {
13 INIT -> pending
14 (render-ui main { type: stack, gap: sm, children: [
15 { type: typography, content: "Unpaid", variant: h4 },
16 { type: button, label: "Pay 40", action: PAY, actionPayload: { amount: 40 } }
17 ] })
18 PAY -> paid when (> ?amount 0)
19 (set @entity.total ?amount)
20 (emit MOVED { event: "PAY" })
21 (render-ui main { type: stack, gap: sm, children: [
22 { type: typography, content: "Paid 40", variant: h4 },
23 { type: button, label: "Ship", action: SHIP }
24 ] })
25 }
26
27 state paid {
28 SHIP -> shipped
29 (emit MOVED { event: "SHIP" })
30 (render-ui main { type: stack, gap: sm, children: [
31 { type: typography, content: "Shipped", variant: h4 },
32 { type: button, label: "New order", action: NEW_ORDER }
33 ] })
34 }
35
36 state shipped {
37 NEW_ORDER -> pending
38 (emit MOVED { event: "NEW_ORDER" })
39 (render-ui main { type: stack, gap: sm, children: [
40 { type: typography, content: "Unpaid", variant: h4 },
41 { type: button, label: "Pay 40", action: PAY, actionPayload: { amount: 40 } }
42 ] })
43 }
44
45 emits {
46 PAY {
47 amount : number!
48 }
49 MOVED -> external {
50 event : string!
51 }
52 @description "Each move names the event it took, so a diagram beside the order can follow it."
53 }
54 }
55
56 page "/checkout" -> Checkout
57}Each one is a single .lolo file.
Planets orbit a central mass under inverse-square gravity.
ready — press Step to advance the orbits
Logic gates combine inputs into outputs that follow their truth table.
Circuit 1 — (A AND B) XOR (A OR B)
Balls bounce off pegs and pile into a bell-shaped histogram.
Press Step to drop a batch of balls, or Run to auto-drop.
orb validate stops you with the code and the line.
$ orb validate checkout.lolo
❌ [ORB_BINDING_PAYLOAD_FIELD_UNDECLARED] orbitals[0 (Orders)].traits[0 (Checkout)].stateMachine.transitions[1].guard[1]: Event 'PAY' uses @payload.amount (.lolo spelling: `?amount` or `@payload.amount`) but has no payload schema defined @ 16:27
💡 declare the field in the event's `emits` payload block: `PAY -> external { amount : <type> }`
❌ [CIRCUIT_DEAD_END_STATE] orbitals[0 (Orders)].traits[0 (Checkout)].stateMachine.states: State 'shipped' has no outgoing transitions - it may be a dead end @ 10:3
💡 Add outgoing transitions or mark as terminal state with isTerminal: true
Error: Schema validation failed with 2 error(s)languages it compiles to
behaviors in the standard library
keyword languages
warnings orb validate allows
Install in one line. Run your first program in the playground.
The language where the rule is the program.