Editor binding reference
Template layers can use mustache expressions and variable paths in many fields (text, colors, images, loop sources, conditions, and more). Values are evaluated in a sandbox: only the variables in scope and the allowed functions listed below are available—no arbitrary JavaScript.
Binding syntax
- Expressions are written as
{{ … }}when the field expects a evaluated result (e.g.{{ brand.colors.primary }},{{ min(padding, 24) }}). - Variable paths use dot notation:
page.width,brand.logos.logo,myVar.nested.key. - Merge order when the same name exists at multiple levels: variables are combined from global (space) → template → page. A value defined on the page wins over template, which wins over global.
Built-in scopes and objects
Scopes
Think of three layers of key/value data that are merged for lookups:
| Scope | Role |
|---|---|
| Global (space) | Space-wide defaults shared across templates. |
| Template | Values stored on the template; override globals when keys match. |
| Page | Per-page values when editing a page instance; override template and global. |
If you set ctaLabel on the page and also on the template, page wins. Use that to keep brand-wide defaults in globals, template-level defaults on the template, and one-off copy on the page.
Objects
These are common top-level objects exposed in expressions (when the page or brand is configured):
| Path | Fields / usage |
|---|---|
$_page | Page metadata when available: e.g. id, name, width, height, backgroundColor. |
brand | Resolved brand tokens for the current render context, e.g. brand.colors.primary, brand.logos.logo, brand.images.picture, brand.copy.tagline. Paths depend on your brand schema; use use() / isDefined() for optional assets so missing tokens do not break the template. |
Example: {{ $_page.width }} for canvas width, {{ use(brand.logos.logoDark, brand.logos.logo, brand.logos.icon) }} for a safe logo URL.
Loops (repeater)
The Loop / Repeater source must resolve to either an array (iterate in order) or an object (iterate entries). It can be supplied as:
- A variable path that points to an array/object, e.g.
items.products. - A bare helper call (no
{{ }}wrapping the whole field), e.g.range(7),monthDayNumbers(year, month). - A single mustache expression that evaluates to an array/object, e.g.
{{ monthDayNumbers(year, month) }}.
Resolution rule: if the path resolves to a non-null value, that value is used as the collection; otherwise the engine may evaluate the field as an expression.
Let <as> be the item variable name you set in the editor (default mental model: item).
| Collection shape | Names available each iteration |
|---|---|
| Array | <as> (element), <as>Index (0-based index). |
| Object | <as> (value), <as>Key (string key), <as>Index (0-based order of keys as enumerated). |
Examples: if Item variable is row, use row, rowIndex, and for objects rowKey. If it is slot in a calendar grid, use slot and slotIndex to bind text or visibility per cell.
Note: Putting {{ }} in a normal text field produces a string. Arrays stringify as comma-separated values, which is rarely what you want for layout—use a repeater layer and bind children to row, rowIndex, etc.
How the repeater layer fits in the tree
The layer that has Loop / Repeater set is not the outer frame around the whole list. At render time that layer is duplicated once per collection item, and each copy is placed as a sibling under that layer’s actual parent in the document. Layout that depends on multiple items at once (e.g. flexWrap for a grid of day cells, row-wide alignment) belongs on a non-repeating parent group above the repeater; per-cell or per-row styling belongs on the repeat layer or its children.
Parent layer
Child layers can read the immediate parent layer node only (not the parent’s children tree):
| Path | Meaning |
|---|---|
$_parent.id | Parent layer id. |
$_parent.type | Parent layer type (e.g. group, text). |
$_parent.props | Parent’s props object (styles, etc.). |
$_parent.text | Parent text content when applicable. |
Use this to align or style a child based on the parent’s identity or props without duplicating data.
Expression helpers
Only the functions below are allowed inside {{ … }} (and in loop sources where documented). Arguments are coerced as needed; invalid inputs often yield empty string, empty array, 0, or a safe fallback as noted.
Core
| Function | Parameters | Returns |
|---|---|---|
use | (...values) — any number of values. | First argument that is not null and not undefined; if none, "". |
isDefined | Same as use. | Same as use. |
min | Same as Math.min — one or more numbers. | Smallest number. |
max | Same as Math.max — one or more numbers. | Largest number. |
abs | x — number. | Absolute value. |
round | x — number. | Rounded integer. |
ceil | x — number. | Ceiling. |
floor | x — number. | Floor. |
clamp | value, min, max — coerced with Number. | If any of the three is NaN, returns value unchanged; else number clipped to [min, max]. |
Array reducers (sums, joins)
For invoice-style totals and joined lists, use sumItems / joinItems to reduce a repeater’s source to a single value. Both accept the same array you would pass to loop.source (typically a dot path like details.items).
| Function | Parameters | Returns |
|---|---|---|
sumItems | items, path optional. | Number total of path read from each item (or each item itself when path is omitted). Currency-formatted strings ("$1,234.50", "₦12,500", "(200)" for negatives) are accepted; non-numeric values are skipped. 0 for non-array input. |
sumLoopItems | Same as sumItems. | Alias for sumItems. |
joinItems | items, path optional, separator optional (default ", "). | String of path values joined with separator. null, undefined, and empty values are skipped so you never see ", , " gaps. "" for non-array input. |
joinLoopItems | Same as joinItems. | Alias for joinItems. |
{{ sumItems(details.items, 'price.new') }}
{{ round(sumItems(details.items, 'price.new') * 1.1) }}
{{ joinItems(speakers, 'name', ' • ') }}
{{ joinItems(tags) }}
Number parsing (currency / formatted strings)
When prices and amounts are stored as formatted strings, convert them with toNumber (alias parseNumber) before doing math. sumItems applies the same normalization internally, so reach for toNumber when you need a single value.
| Function | Parameters | Returns |
|---|---|---|
toNumber | value, fallback optional (default 0). | Number parsed from value, stripping currency symbols ($ € £ ¥ ₦ ₹ ₽ ₩ ¢ ฿ ₪ ₫ ₱ ₴ ﷼), currency codes (USD, EUR, NGN, kr, …), thousands commas / narrow / thin spaces, a trailing %, and accounting parentheses (negative). Returns fallback when the value is blank or unparseable. |
parseNumber | Same as toNumber. | Alias for toNumber. |
{{ toNumber('$1,234.50') }} // 1234.5
{{ toNumber(invoice.subtotal) * 1.1 }} // works even if subtotal is "$199.99"
{{ toNumber(invoice.discount, 0) }} // safe 0 default when blank
{{ round(toNumber(price.new) - toNumber(price.discount)) }}
{{ parseNumber('(1,200)') }} // -1200 (accounting style)
Strings using , as the decimal mark ("1.234,56") are not auto-converted — that pattern is ambiguous against the en-US thousands convention. Normalize on input first.
Calendar and loop arrays
Month is always 1–12. Date math uses UTC. Array-producing helpers cap very large ranges internally (guardrail for templates).
| Function | Parameters | Returns |
|---|---|---|
range | count or start, end (inclusive). Integers are truncated. | count form: [0, …, count - 1] for count ≥ 0; empty if invalid or too large. start,end form: inclusive integer range from min(start,end) to max(start,end); empty if span exceeds guardrail. |
daysInMonth | year, month (1–12). | Integer day count in that month, or 0 if invalid. |
daysInAMonth | Same as daysInMonth. | Same as daysInMonth. |
yearRange | startYear, endYear — truncated integers. | Array of years from low to high inclusive; empty if invalid or span too large. |
monthDayNumbers | year, month. | Array [1, 2, …, lastDay] for that month; empty if invalid. |
calendarMonthSlots | year, month, weekStartsOn optional (default 1 = Monday). weekStartsOn: 0 = Sunday … 6 = Saturday. | Array of length 42 (6×7): null for padding cells, 1-based day number for in-month cells. |
monthNames | None. | Array of 12 full English month names ("January" … "December"). |
monthNamesShort | None. | Array of 12 short labels ("Jan" … "Dec"). |
weekdayNames | None. | Array of 7 full weekday names, Sunday first. |
weekdayNamesShort | None. | Array of 7 short weekday labels, Sunday first. |
Color
All color inputs accept strings ("#rgb", "#rrggbb", "rgb(...)", etc.) or, for some APIs, a number interpreted as a hex RGB integer. On errors, functions fall back to the input color string, #888888, or #ffffff as implemented.
| Function | Parameters | Returns |
|---|---|---|
lighten | color, amount optional (default 1). | Hex string (chroma brighten). |
darken | color, amount optional (default 1). | Hex string. |
saturate | color, amount optional (default 1). | Hex string. |
desaturate | color, amount optional (default 1). | Hex string. |
alpha | color, a — alpha 0–1. | Hex string with alpha (chroma). |
mix | color1, color2, ratio optional (default 0.5). | Hex string blend. |
shade | color, ratio optional (default 0.5). | Hex string — mix toward black. |
tint | color, ratio optional (default 0.5). | Hex string — mix toward white. |
scaleColors | colors (single color or array of stops), tOrN. | If tOrN is an integer ≥ 1: array of that many sampled hex colors. Otherwise: single hex at position t in 0–1 along the scale. |
contrast | color1, color2. | Number — WCAG contrast ratio (higher = more difference; 4.5+ is a common text target). |
blend | color1, color2, mode optional (default "multiply"). Modes: multiply, darken, lighten, screen, overlay, burn, dodge. | Hex string. |
average | One array of colors, or multiple color arguments. | Hex string average. |
colorValid | color. | true only if color is a string and chroma accepts it; otherwise false. |
hex | color. | Hex string normalized. |
colorCss | color. | CSS color string (e.g. rgb(...), rgba(...)). |
temperature | kelvin — optional, default 6500. | Hex string for black-body style temperature (clamped 0–30000). |
luminance | color, lum — target luminance 0–1. | Hex string adjusted to that luminance. |
getLuminance | color. | Number in 0–1 (relative luminance). |
isLight | color, threshold optional (default 0.5). | true if getLuminance(color) > threshold. |
isDark | color, threshold optional (default 0.5). | true if getLuminance(color) < threshold. |
For more examples of use / isDefined and brand paths, see Template expressions.