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: 3There 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.
r=119.3px, v=2.25
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.
0 ball(s) landed this step — bin 4 leads with 15 total
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.