Pebble Functions
A set of utility functions registered by Invirt that can be used inside Pebble templates.
request()
Returns the current http4k Request (wrapped in an InvirtRequest).
This function is required inside macros, where the context request object
is not visible. Outside macros either form works.
{% macro requestSummary() %}
{{ request().uri }}
{{ request().method }}
{% endmacro %}
{{ request.method }}
{{ request.query("q") }}
errors()
Returns the validation errors object (io.validk.ValidationErrors), or null if there are no validation
errors for the current request. Required inside macros — outside, the
errors context object is equivalent.
Read more about validation here.
{% if errors().hasErrors("name") %}
<div class="text-error">{{ errors().error("name") }}</div>
{% endif %}
json(value)
Renders the given object as a JSON string. Typically used when embedding model data into a JavaScript context.
<div id="map" data-map-place='{{ json(model.place) | raw }}'></div>
jsonArray(value)
Same as json(), but always renders the value as a JSON array. When value is not a collection it is
wrapped in a single-element array.
<div id="map" data-map-places='{{ jsonArray(model.places) | raw }}'></div>
uuid()
Returns a new time-ordered UUIDv7 as a hex string (no dashes). Convenient for unique DOM ids in templates.
<input type="text" id="field-{{ uuid() }}"/>
currencyFromMinorUnit(minorUnitAmount, currency)
Formats a minor-unit currency value (pence/cents) as a human-readable string using the currency's symbol and default fraction digits.
{{ currencyFromMinorUnit(order.totalMinorUnit, "GBP") }} // £12.50
pluralize(count, singular, plural)
Returns singular when count == 1 and plural otherwise.
You have {{ model.count }} {{ pluralize(model.count, "message", "messages") }}.
dateRange(from, to)
Renders a pair of LocalDates as one phrase that says each part only once: a null to (how a single-day
entry is modelled) or a to equal to from is that one day, a range inside one calendar year carries the
year on its closing date alone, and a range crossing years spells both out. Both ends carry the English
ordinal suffix on the day of month.
{{ dateRange(model.openFrom, model.openTo) }}
{# → "5th November – 5th December 2026" #}
{{ dateRange(model.openFrom, null) }}
{# → "5th November 2026" #}
A from that is not a LocalDate, or a to that is neither a LocalDate nor null, is a template bug and
fails rather than rendering something plausible. The phrasing is
formatDateRange's default; a template that needs another
pattern formats the range in Kotlin and passes the string in its model.
dateWithDaySuffix filter
Formats a LocalDate, LocalDateTime or Instant using a DateTimeFormatter pattern, inserting the
English ordinal suffix on the day of month (1st, 2nd, 3rd, ...).
{{ model.deliveryDate | dateWithDaySuffix("EEEE, MMMM d yyyy") }}
{# → "Sunday, March 1st 2026" #}
An Instant is a point on the timeline rather than a calendar date, so it takes a zone argument (a zone
id) saying which zone the date is read in, and the filter fails if it is missing. 2026-08-31T23:02:00Z is
the 31st of August in UTC and the 1st of September in Europe/London, so there is no zone the filter could
pick for you that isn't the wrong day for someone.
{{ model.dispatchedAt | dateWithDaySuffix("EEEE, MMMM d yyyy", zone="Europe/London") }}
{# → "Tuesday, September 1st 2026" #}
zone means nothing to a LocalDate or a LocalDateTime, which are calendar values already, and is
ignored if passed.