Order Format & Tokens
Foodlang has two sides. The recipe side (.food / .food.yaml) describes how
to make something. The order side described here describes what a customer
wants, chosen from a pre-published, versioned menu.
An order never inlines a recipe. It references item identifiers — each of
which is assumed to already have its own .food receipt recipe on the
restaurant's side — plus the customer's variant params and args. That keeps
orders tiny, stable across menu revisions, and safe to put in a QR code or a
link.
Try it live on the Order page.
1. The .food order code (KDL)
The canonical, human-readable order is a strict-KDL document rooted at an
order node:
order "Sakura Ramen House" {
menu "spring-2026" version=3
service takeout
line tonkotsu_ramen 2 {
spice medium
noodles firm
egg
extra_chashu
}
line gyoza 1 {
style pan_fried
}
line green_tea 2 {
temp iced
}
note "no scallions"
}
Grammar
| Node | Form | Meaning |
|---|---|---|
order |
order "<name>" { … } |
Root. The string is the restaurant's display name. |
menu |
menu "<id>" version=<n> |
Which published menu, and which version. Both are required so the kitchen resolves item ids against the exact menu the customer saw. |
service |
service <dine_in|takeout|delivery> |
Fulfilment method. |
line |
line <item_id> <qty> { … } |
One ordered item. item_id is a bare identifier that maps to a .food recipe; qty is a positive integer. The child block is optional. |
| select param | <key> <value> |
A single-choice variant (e.g. spice medium). |
| bare arg | <ref> |
A boolean add-on / flag (e.g. egg, extra_chashu). |
note |
note "<text>" |
Free-text kitchen note. |
Because every construct is valid strict KDL, an order code parses with any
KDL v1 parser and passes Foodlang's isStrictKdl() check. A one-line compact
form (using ; separators) is equivalent:
order "Sakura Ramen House" { menu "spring-2026" version=3; service takeout; line tonkotsu_ramen 2 { spice medium; noodles firm; egg; extra_chashu }; note "no scallions" }
Design rules
- Ids over recipes.
line tonkotsu_ramenrefers to the restaurant'stonkotsu_ramen.food. The order does not, and must not, restate the recipe. - Version everything. An id only means something within a menu version.
Ship the
menu … version=line so a re-priced or renamed menu can't silently change what a customer ordered. - Params are the customer's, not the kitchen's. Selects (
spice medium) and bare flags (egg) are the only customer-authored data. Prices, descriptions, and preparation live on the recipe side.
2. The condensed order token (FOT/1)
The KDL code is readable but verbose. For a small, dense QR or a short share link, Foodlang defines a single-line wire format: the Foodlang Order Token, version 1.
fot1~sakura-ramen-house~spring-2026:3~t~tonkotsu_ramen*2.spice-medium,noodles-firm,egg,extra_chashu;gyoza*1.style-pan_fried~no scallions
Grammar
token = "fot1" "~" rid "~" menu ":" version "~" svc "~" lines [ "~" note ]
lines = line *( ";" line )
line = item_id "*" qty [ "." args ]
args = arg *( "," arg )
arg = key "-" value ; a select param
| ref ; a bare add-on / flag
svc = "d" / "t" / "x" ; dine_in / takeout / delivery
| Section | Example | Notes |
|---|---|---|
| Magic + version | fot1 |
Literal prefix; bump the digit for future formats. |
rid |
sakura-ramen-house |
Restaurant id ([a-z0-9-]). |
menu:version |
spring-2026:3 |
Menu id and integer version. |
svc |
t |
One letter: d, t, or x. |
lines |
tonkotsu_ramen*2.spice-medium,egg |
;-separated. Each is id*qty then optional .args. |
note |
no scallions |
Optional. Always last, so it may contain any character except ~. |
Reserved characters: ~ ; . , * : -. Item ids, keys, and values are
[a-z0-9_] (underscore, never dash — dash is the select separator). This keeps
tokens URL-safe without escaping, apart from the note.
Round-trip
FOT/1 is loss-free with respect to the KDL order code: decode a token, and you
can regenerate byte-identical .food order code (given the same menu). The Order
page does exactly this — the token is what it embeds in the QR and the share
link, and what it decodes when one is opened.
3. Sending an order
An order can reach the clerk three ways. All are generated client-side; the first two need no network at all.
a. Offline QR
The QR encodes either the FOT/1 token (default — smallest) or the full
compact .food code. The clerk scans it at the counter. Nothing leaves the
device.
b. Condensed token
Copy the fot1~… string and send it however you like — it is short enough to
read aloud or type. The kitchen's Foodlang tooling decodes it back to an order.
c. Online share link
For remote / ahead-of-time ordering, the token rides in a URL fragment:
https://foodlang.com/order.html#o=<url-encoded FOT/1 token>
Because the token is in the # fragment, it is never sent to the server —
the page reconstructs the order entirely in the browser. Opening the link
selects the right restaurant and rebuilds the exact cart, ready to confirm or
re-share. On devices with the Web Share API, the Share order button hands
this link to the native share sheet (Messages, Mail, etc.).
The fragment approach means the same link works whether the recipient is online or offline once loaded, and no order data is logged by any host.