---
name: mystique-templates
scope: frontend
description: "Template helper reference (30+ helpers with syntax and examples)"
load: on-demand
relevant-skills: [fluent-mystique-builder, fluent-mystique-validate]
---

# Mystique Template Helper Reference

Complete reference for template strings and helpers available in Fluent Commerce Mystique manifests. Template strings use Mustache syntax `{{expression}}` to create dynamic values that bind to data, perform transformations, and execute logic.

Do not use helpers that are not documented here. Guessing will lead to silent failures.

---

## Basic Property Access

```json
{
  "simple": "{{order.ref}}",
  "nested": "{{order.customer.firstName}} {{order.customer.lastName}}",
  "attribute": "{{order.attributes.byName.vipStatus}}"
}
```

**Special property: `byName`** -- Entity attributes in GraphQL return as arrays. Use `byName` to access by name directly instead of array indexing.

---

## Context Variables

These are available without any query. No helper needed.

### activeUser

| Property    | Access                          | Description              |
|-------------|----------------------------------|--------------------------|
| username    | `{{activeUser.username}}`        | Current user's username  |
| firstName   | `{{activeUser.firstName}}`       | First name               |
| timezone    | `{{activeUser.timezone}}`        | User's timezone          |

### activeContext

| Property | Access                         | Description                    |
|----------|--------------------------------|--------------------------------|
| id       | `{{activeContext.id}}`         | Current context ID (retailer or location) |
| ref      | `{{activeContext.ref}}`        | Current context ref            |

### activeRetailer

| Property | Access                          | Description                |
|----------|---------------------------------|----------------------------|
| id       | `{{activeRetailer.id}}`        | Current retailer ID        |
| ref      | `{{activeRetailer.ref}}`       | Current retailer ref       |

### activeLocation

| Property | Access                          | Description                |
|----------|---------------------------------|----------------------------|
| id       | `{{activeLocation.id}}`        | Current location ID        |
| ref      | `{{activeLocation.ref}}`       | Current location ref       |

---

## String Helpers

### toLowerCase

Convert a string to lowercase.

```json
"{{toLowerCase order.type}}"
```

### toUpperCase

Convert a string to uppercase.

```json
"{{toUpperCase order.customer.lastName}}"
```

### humanify

Capitalize the first letter of a string.

```json
"{{humanify order.ref}}"
```

### concat

Concatenate two strings with an optional separator (default is empty string).

```json
"{{concat firstName lastName separator=' '}}"
```

### stringify

Convert a JSON object into a string representation.

```json
"{{stringify order.attributes.byName.payload}}"
```

### partialStringMatch

Returns `true` if the first string appears in the second string. Case insensitive.

```json
"{{partialStringMatch 'item1' 'eM1'}}"
```

### preserveWhitespace

Keeps content's white space as-is instead of HTML's default of collapsing to a single space.

```json
"{{preserveWhitespace text}}"
```

### decodeUrlParams

Decodes URL-encoded parameters.

```json
"{{decodeUrlParams 'TEST%3A%3AL%2FXL'}}"
```
Result: `TEST::L/XL`

### currentUrlParams

Returns the part of the URL containing query parameters after the `?` symbol. The template does not use the `{{}}` double-brace format -- use triple braces to avoid HTML escaping.

```json
"#/search?{{{currentUrlParams}}}"
```

### readFromParams

Takes the name of a URL parameter and returns its value.

```json
"{{readFromParams 'status'}}"
```

### readArrayFromParams

Takes the name of a URL parameter and returns the array of values. Useful for multi-select filters.

```json
"{{readArrayFromParams 'selectedStatuses'}}"
```

### placeholderText

Inserts plain text with optional formatting and a fallback value if text is missing.

| Parameter     | Default    | Description                   |
|---------------|------------|-------------------------------|
| `color`       | `#00A9E0`  | Text colour                   |
| `fontWeight`  | `bold`     | Font weight                   |
| `defaultValue`| `-`        | Fallback if value is missing  |

```json
"{{placeholderText text color='#fffaaa' fontWeight='normal' defaultValue='-'}}"
```

---

## Date Helpers

**CRITICAL for backend queries:** Always use `_locale='en'` and UTC (`true` third parameter) for query variables to avoid localized digits (e.g., Arabic numerals).

### dateFormat (aka dateStringFormatter)

Formats a date string. Accepts an optional format pattern and timezone flag.

| Parameter | Position | Description                                                      |
|-----------|----------|------------------------------------------------------------------|
| date      | 0        | Date object or date-formatted string                             |
| format    | 1        | Optional format pattern (e.g., `'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'`) |
| utc       | 2        | Optional boolean. `true` forces UTC.                             |
| `_locale` | named    | Force locale (e.g., `_locale='en'`).                             |

```json
{
  "display": "{{dateFormat order.createdOn}}",
  "iso": "{{dateFormat order.createdOn 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'}}",
  "queryVar": "{{dateFormat (dateAdd day=-1) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true _locale='en'}}"
}
```

### dateAdd

Add an amount of time to a date. Date is optional (defaults to now).

| Modifier        | Example                    |
|-----------------|----------------------------|
| `day=N`         | `{{dateAdd day=3}}`        |
| `month=N`       | `{{dateAdd month=1}}`      |
| `year=N`        | `{{dateAdd year=-1}}`      |

```json
"{{dateAdd order.createdOn day=3}}"
```

### dateSubtract

Subtract an amount of time from a date. Date is optional (defaults to now).

```json
"{{dateSubtract order.createdOn day=5}}"
```

### dateRelative

Convert a date into a relative display format.

```json
"{{dateRelative order.expiryTime}}"
```
Result: `"10 minutes ago"`

### dateFormatByLocale

Format a date based on the user's browser language. English (UK/AU) and many other locales use `dd/mm/yyyy`; English (US) uses `mm/dd/yyyy`.

```json
"{{dateFormatByLocale order.createdOn}}"
```

### placeholderDate

Inserts a formatted date with styling options and a fallback if no date is provided.

| Parameter      | Default    | Description                   |
|----------------|------------|-------------------------------|
| `color`        | `#00A9E0`  | Text colour                   |
| `fontWeight`   | `bold`     | Font weight                   |
| `defaultValue` | `[...]`    | Fallback if date is missing   |

```json
"{{placeholderDate date color='#00A9E0' defaultValue='[...]'}}"
```

### currentTimezone

Returns the user's current system timezone in TZ identifier format.

```json
"{{currentTimezone}}"
```

---

## Number Helpers

### currency

Convert a number to currency format using `Intl.NumberFormat`.

| Parameter        | Required | Description                                |
|------------------|----------|--------------------------------------------|
| number           | Yes      | The numeric value                          |
| currency code    | Yes      | ISO currency code (e.g., `'AUD'`)         |
| `_locale`        | No       | Force locale (e.g., `_locale='en-AU'`)     |
| `_decimalPlaces` | No       | Decimal places (default 2)                 |

```json
{
  "basic": "{{currency totalPrice 'AUD'}}",
  "full": "{{currency 123.87 'AUD' _locale='en-AU' _decimalPlaces=3}}"
}
```

### add

Add two numbers. Optional `_decimalPlaces` (default 2).

```json
"{{add 1 2}}"
```

### subtract

Subtract one number from another. Optional `_decimalPlaces`.

```json
"{{subtract 50.32 20.11 _decimalPlaces=2}}"
```
Result: `30.21`

### multiply

Multiply two numbers. Optional `_decimalPlaces`.

```json
"{{multiply 3 4}}"
```

### divide

Divide one number by another. Optional `_decimalPlaces`.

```json
"{{divide 12 4 _decimalPlaces=3}}"
```
Result: `3.000`

### pow

Raise one number to the power of another. Optional `_decimalPlaces`.

```json
"{{pow 3 2}}"
```
Result: `9`

### formatNumber / getMetricStepByTimePeriod

Calculates step sizes by time period for metric displays.

---

## Logic Helpers

### eq

Compare two values. Returns `true` if equivalent.

```json
"{{eq order.status 'BOOKED'}}"
```

### ne

Compare two values. Returns `true` if not equivalent.

```json
"{{ne order.status 'CANCELLED'}}"
```

### lt

Returns `true` if first value is less than second.

```json
"{{lt order.items.count 3}}"
```

### gt

Returns `true` if first value is greater than second.

```json
"{{gt order.items.count 3}}"
```

### lte

Returns `true` if first value is less than or equal to second.

```json
"{{lte order.items.count 3}}"
```

### gte

Returns `true` if first value is greater than or equal to second.

```json
"{{gte order.items.count 3}}"
```

### and

Returns `true` if all arguments are truthy. In JavaScript, strings, numbers, and objects are truthy; `null`, `undefined`, `0`, and `""` are falsy.

```json
"{{and (eq order.status 'BOOKED') (gt order.items.count 3)}}"
```

**Common pattern** -- existence check for conditions and links:
```json
"{{and customer.id}}"
```

### or

Returns `true` if any argument is truthy.

```json
"{{or order.status order.items.count}}"
```

### not

Negates a boolean expression.

```json
"{{not (eq order.status 'CANCELLED')}}"
```

### if / unless

Conditional rendering (block helpers in Handlebars).

```json
"{{if (eq order.status 'BOOKED') 'Active' 'Inactive'}}"
```

### in

Check if a value is in a set.

### switch

Switch-case pattern for value mapping.

### firstDefinedValue

Returns the first non-null, non-undefined value from the arguments.

```json
"{{firstDefinedValue null undefined 10}}"
```
Result: `10`

### anyMatch

Performs conditional checks on structured data (lists, arrays). Takes three parameters: path, value, and comparison function.

```json
"{{anyMatch 'node.entity.field' 'delta' 'eq'}}"
```

### hasRole

Check if the current user has a specific role.

---

## Array Helpers

### arraySum

Total up numeric values from within an array of objects using a JSONPath.

```json
"{{arraySum order.items 'node.totalPrice'}}"
```

### len / length

Get the length of an array or string. Use `edges.length` for connection counts:

```json
"{{orders.edges.length}}"
```

### pluralize

Pluralize a word based on a count.

### placeholderArray

Inserts a list of values joined by a separator, with optional truncation.

| Parameter    | Default   | Description                                    |
|--------------|-----------|------------------------------------------------|
| `separator`  | `, `      | Separator between values                       |
| `charCutoff` | none      | Maximum characters before truncation           |
| `color`      | `#00A9E0` | Text colour                                    |
| `fontWeight` | `bold`    | Font weight                                    |
| `defaultValue`| `-`      | Fallback if array is empty                     |

```json
"{{placeholderArray arr separator='*' charCutoff=10}}"
```

---

## i18n Helper

### i18n

Translate a value into another language. Joins multiple string arguments into an i18n key.

| Parameter   | Description                                              |
|-------------|----------------------------------------------------------|
| key parts   | Any number of strings joined into a key                  |
| `_fallback` | Fallback value if key is not found                       |

```json
{
  "basic": "{{i18n 'fc.om.order.type.' node.type _fallback=node.type}}",
  "concatenated": "{{i18n 'fc.om.order' '.' 'status'}}"
}
```

The concatenated form builds the key `fc.om.order.status` from multiple parts.

---

## Barcode Helper

### barcode

Generate a barcode image for a given string.

| Parameter     | Position | Description                                                       |
|---------------|----------|-------------------------------------------------------------------|
| value         | 0        | The string to encode                                              |
| format        | 1        | Optional encoding type. Auto-detected if not specified.           |
| displayText   | 2        | Optional boolean. `false` hides the text below the barcode.      |

**Supported encoding types:** `CODE128B`, `EAN-13`, `EAN-8`, `UPC-A`, `CODE39`, `ITF-14`, `MSI`, `pharmacode`, `codabar`.

```json
{
  "auto": "{{barcode fulfilmentById.ref}}",
  "explicit": "{{barcode '1234 abc' 'CODE128B'}}",
  "noText": "{{barcode '1234' 'EAN-13' false}}"
}
```

---

## URL Helpers

### currentUrlParams

Returns the query parameter string from the current URL. Use triple braces `{{{...}}}` to avoid HTML escaping.

```json
"#/inventorySearch/product/{{node.productRef}}?{{{currentUrlParams}}}"
```

### decodeUrlParams

Decodes URL-encoded strings.

```json
"{{decodeUrlParams 'TEST%3A%3AL%2FXL'}}"
```

---

## Common Patterns

### Backend query-safe date variable

Always use `_locale='en'` and UTC for date variables in GraphQL queries:

```json
{
  "createdFrom": "{{dateFormat (dateSubtract day=7) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true _locale='en'}}",
  "createdTo": "{{dateFormat 'now' 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true _locale='en'}}"
}
```

### Conditional link rendering

Both `link` and `condition` must be set. The condition must be truthy for the link to render:

```json
{
  "value": "{{customer.firstName}} {{customer.lastName}}",
  "link": "#/customer/{{customer.id}}",
  "condition": "{{and customer.id}}"
}
```

### Status with i18n and fallback

```json
"{{i18n 'fc.om.order.status.' status _fallback=status}}"
```

### Currency with item-level currency code

```json
"{{currency totalPrice items.edges.0.node.currency}}"
```

---

## Custom Template Helper Registration

All built-in helpers above are provided by the Mystique host. To add custom helpers, use the `TemplateRegistry` in your SDK component project:

```typescript
// src/templates/formatCurrency.ts
export const formatCurrency = (amount: number, currency: string): string =>
  `${currency} ${Number(amount).toFixed(2)}`;

// src/index.tsx
import { TemplateRegistry } from 'mystique/registry/TemplateRegistry';
import { formatCurrency } from './templates/formatCurrency';

TemplateRegistry.register('acme.helpers.format-currency', formatCurrency);
```

**Manifest usage:** `"{{acme.helpers.format-currency node.totalPrice 'AUD'}}"`

**Alias format:** `TemplateRegistry.register()` accepts `string | string[]` as the first parameter — unlike `ComponentRegistry` and `FieldRegistry` which require `string[]`. Use the `<namespace>.helpers.<kebab-name>` convention for consistency.

For the full SDK registration reference (ComponentRegistry, FieldRegistry, TemplateRegistry), see [mystique-sdk.md](mystique-sdk.md).
