Host data and events
A spec declares its own starting state, but most real interfaces show data your app already has. Your app can set state at any time, and listen to everything that changes.
Providing data
ui.state.set("products", await fetchProducts());
ui.state.set("user", { name: "Ada", plan: "pro" });A spec reads host data like any other state:
card
text "{plural(len(products), 'product')}" style=title
each items=products as=p key={p.id}
row
text "{p.name}"
text "{money(p.price)}" align=rightWhat your app passes is copied into plain, frozen SayShape data. Functions, class instances and cycles are refused with a clear error, so a spec can only ever see data, never your objects. Values your app sets are never replaced by a state line in the spec.
When a model writes a spec that reads host data, tell the parser and the model client which names your app supplies (knownNames for parse, stateNames for generateSpec), so reading them isn't reported as an unknown name.
Reacting to changes
ui.on("change", ({ key, value }) => {
if (key === "cart") saveCart(value);
});Writes to items replace the whole list, so a change to cart[1].qty arrives as a change event for cart with the new list.
Handling actions
emit: is how a spec asks your app to do something it can't do itself:
ui.on("action", ({ name, value }) => {
switch (name) {
case "checkout": return startCheckout(value);
case "open_order": return router.push(`/orders/${value}`);
}
});SayShape never makes a network request because of a spec: images aside (Images), anything that leaves the page goes through your handlers. Which actions exist is a contract between your app and the model; describe them in the model guide's actions option so the model uses the names you handle (The model guide).
Moving between screens
ui.go("cart"), ui.back(), ui.screens, ui.currentScreen and the navigate event let your app follow and drive a spec's screens.
Not built yet
SayShape doesn't yet have declared data sources (a spec saying "load orders from here") or host commands that return results to the spec. Today your app fetches data and calls state.set.