Pages built in Build Studio are plain HTML until the runtime attaches. It scans for data-* attributes, wires them up, and keeps them in sync as data changes.
No build step and no framework. You can hand-write these attributes into a page, and the property panel writes the same ones when you configure an element visually.
The full attribute set
| Attribute | Purpose |
|---|---|
data-bind | Set textContent from a path or expression |
data-bind-html | Set sanitized innerHTML |
data-bind-attr-<name> | Set an HTML attribute — data-bind-attr-src="data.image" |
data-bind-class | Set className |
data-bind-style-<prop> | Set one CSS property — camelCase, e.g. data-bind-style-backgroundImage |
data-show / data-hide | Conditional visibility |
data-format | Format a bound value |
data-format-opt-<name> | An option for that format |
data-source | Fetch data and set a context for children |
data-source-payload | Arguments for the source call |
data-bind-each | Marks the child that is repeated per array item |
data-action | Run a call on an event |
data-payload | Arguments for the action |
data-trigger | Which event fires it |
data-confirm | Ask before running |
data-on-success | Effect chain after success |
data-on-error | Effect chain after failure |
Binding values
<span data-bind="cart.count"></span>
<span data-bind="data.price" data-format="currency" data-format-opt-currency="EUR"></span>
<img data-bind-attr-src="data.image" data-bind-attr-alt="data.name">
<div data-bind-class="data.status"></div>
<div data-bind-style-width="data.percent + '%'"></div>An attribute binding that resolves to null, undefined or false removes the attribute rather than setting it empty.
It sets innerHTML through a sanitizer rather than assigning raw markup.
Lists
A list is two attributes working together: a container that fetches, and one child marked as the row template.
<div data-source="product.list"
data-source-payload='{"options":{"pageSize":12}}'>
<article data-bind-each>
<img data-bind-attr-src="data.image">
<h3 data-bind="data.name"></h3>
<span data-bind="data.price" data-format="currency"></span>
</article>
</div>data-bind-each takes no value. The element carrying it is cloned once per item in the returned array, and paths inside it resolve against that row.
Without a data-bind-each child, data-source still sets a context — which is what you want when the source returns a single object rather than a list.
Where a path resolves
The runtime walks contexts in order and takes the first that has the path:
1. Row context — the current item, inside a data-bind-each template.
2. Source context — data from the nearest data-source ancestor.
3. Reactive state — appmint.state, which holds the cart mirror, the signed-in customer, and anything you set yourself.
Nothing matching renders empty rather than erroring.
Actions
<button data-action="cart.add"
data-payload='{"id":"{{sk}}","name":"{{data.name}}","unitPrice":{{data.price}}}'
data-on-success="notify:Added to cart | refresh"
data-on-error="notify-error:Could not add">
Add to cart
</button>Triggers
data-trigger overrides the default event: click, submit, change or inview.
Defaults are sensible — buttons and links fire on click, forms on submit, inputs and selects on change. inview fires when the element scrolls into view, which is how you lazy-load a section.
Payload forms
data-payload accepts five shapes:
| Form | Meaning |
|---|---|
| (omitted) | No arguments |
form | Serialize the containing form |
this | The current row or context object |
this.<prop> | One property of it |
{"k":"v"} | A JSON object, with {{path}} interpolation inside string values |
Anything else is passed as a literal.
Confirmation
<button data-action="order.cancel"
data-payload="this.id"
data-confirm="Cancel order {{data.number}}?">Cancel</button>The action does not run unless confirmed. The message interpolates like any other binding.
Visibility
<div data-show="customer.isSignedIn">Welcome back</div>
<div data-hide="cart.count">Your cart is empty</div>What you can reference
Anything the runtime knows about:
| Prefix | What it holds |
|---|---|
cart.* | count, total, items, isOpen — mirrored from the cart store |
customer.* | The signed-in customer, and isSignedIn |
data.* | The current row or source context |
| (anything else) | Keys you set yourself with state.set |