Skip to main content

Variables & data

Every template is bound to a typed data model through its context key. The model defines which fields are available for substitution at send time.

The model​

Each context key (Order, Event, User, …) corresponds to a fixed shape maintained by backend code:

  • Top-level fields (Order.OrderNumber, Order.CustomerName)
  • Nested objects (Order.DeliveryAddress.City)
  • Collections (Order.LineItems)
  • Typed values (strings, numbers, dates, booleans)

When a render is requested, the caller supplies an instance of that model.

Referencing fields in MJML​

Template authors reference fields directly inside their MJML. The system replaces every reference with the corresponding value from the supplied data.

Missing fields are flagged at validation time — typos are caught when the template is saved, not at 3 a.m. on send day.

Formatting​

Values are transformed at the point of use with filters:

  • Dates render automatically in each recipient's timezone, language, and clock preference via the date filter ({{ Order.ScheduledAt | date }}); a start–end pair becomes a single localized string with date_range. Authors don't pass format strings or timezones — output is consistent for everyone.
  • Defaults can be supplied inline so an empty field doesn't leave a blank spot in the email ({{ Order.Note | default: '—' }}).
  • Lists can be joined into human-readable strings with a chosen separator.

The formatting layer is consistent across all templates — see Filters for the full set.

Why typed models matter​

  • Compile-time safety on the backend. When the model class is updated, the compiler points at every code path that needs adjustment.
  • Validation on the template. Saving a template that references a non-existent field fails fast.
  • Clear contracts. Each template documents itself: read the context key, look up the model, you know exactly what data it can use.

What this means for authors​

You can confidently reach for any field on the model. You don't need to worry about whether the value is null, missing, or wrong-typed — the system either substitutes a sensible representation or rejects the change before it ships.