Skip to main content

Writing templates

SHIPM8 templates use Handlebars as the underlying engine. Any Handlebars feature works here, and SHIPM8 adds its own formatting and transformation helpers on top.

Simple placeholders

Wrap any field name in double curly braces to insert its value.

Template

Voyage confirmed for {{vesselName}}, calling at {{port}}.

Data

{ "vesselName": "Ocean Star", "port": "Rotterdam" }

Result

Voyage confirmed for Ocean Star, calling at Rotterdam.

Looping over lists

Use #each to iterate over an array. Inside the block the context shifts to each item.

Template

Port rotation:
{{#each portCalls}}
- {{port}} ETA {{eta}}
{{/each}}

Data

{
"portCalls": [
{ "port": "Amsterdam", "eta": "2024-03-10" },
{ "port": "Hamburg", "eta": "2024-03-13" },
{ "port": "Antwerp", "eta": "2024-03-15" }
]
}

Result

Port rotation:
- Amsterdam ETA 2024-03-10
- Hamburg ETA 2024-03-13
- Antwerp ETA 2024-03-15

Reaching outside a loop (root and parent)

Inside an #each block the scope changes to the current item. Use @root to reach the top-level data object, or ../ to step one level up to the parent scope.

Root selector

Vessel: {{vesselName}}
{{#each portCalls}}
{{port}} — vessel: {{@root.vesselName}}
{{/each}}

Parent selector

Vessel: {{vesselName}}
{{#each portCalls}}
{{port}} — vessel: {{../vesselName}}
{{/each}}

Both produce the same result:

Vessel: Blue Marlin
Amsterdam — vessel: Blue Marlin
Hamburg — vessel: Blue Marlin
Antwerp — vessel: Blue Marlin

Combining helpers (sub-expressions)

Helpers can be nested inside one another using parentheses — Handlebars calls these sub-expressions. The inner expression is evaluated first and its result is passed to the outer helper.

{{leastDecimals (numberFormat cargo.tonnage 'F03')}}

With cargo.tonnage = 45000.500, this first formats the number to 45000.500, then strips the trailing zero, giving 45000.5.

For the full sub-expression syntax see the Handlebars documentation.