Template Syntax

Postmark Template Syntax

Postmark Templates use a very simple, yet very powerful, language called Mustachio. Mustachio has its roots with Mustache, but includes a few advanced features that make it great for authoring plain text and html emails.

Here's everything you need to know about the language.

Variable Interpolation:

"Variable Interpolation" is the heart and soul of any templating language.

If you have a template model like this (represented as JSON):

{
    "person" : {
       "first_name" : "Andrew",
    }
}

And this template:

Hello {{ person.first_name }}

Mustachio will produce this content when you combine the two:

Hello Andrew

If you've used Mustache.js, this should be very familiar. But Mustachio has a few more capabilities that make writing templates a breeze.

Scoping:

Sometimes we'll have more complex models, and so scoping to a particular property will make the markup easier to read:

{{#person}}
   Hello {{first_name}} 
{{/person}}

Notice that if we're building a section of the template that uses multiple properties from "person", we don't need to keep repeating "person." with each variable interpolation.

Collection Handling:

Let's say we have this more complicated model:

{
    "company_name" : "ACME Rockets, Inc.",
    "employees" : [
         { "name" : "Wile E. Coyote"},
         { "name" : "Road Runner"}
    ]
}

And this template:

{{ company_name }} Employees:
<ul>
{{#each employees}}
	<li>{{ name }}</li>
{{/each}}
<ul>

Mustachio will combine these and produce the following HTML:

ACME Rockets, Inc. Employees
<ul>
	<li>Wile E. Coyote</li>
	<li>Road Runner</li>
</ul>

Advanced Interpolation:

If we've scoped our template to a property of a model, we may want to "reach up" to a property in the outer scope. For example, let's say we wanted to change the content from the Collection Handling example above to look like this:

<ul>
	<li>Wile E. Coyote works for: ACME Rockets, Inc.</li>
	<li>Road Runner works for: ACME Rockets, Inc.</li>
</ul>

We can use a special interpolation syntax to do this without needing to repeat the values in our template model:

<ul>
{{each employees}}
  <li>{{name}} works for: {{../company_name}}</li>
{{/each}}
</ul>

Note the ../ in the template, which just means "go up one level" in my template model and look for the property name that follows. You can go up as many levels in your model as needed by including ../ multiple times at the start of your {{ ... }} section.

Advanced Value Handling

Mustachio is permissive about missing values in your models. If you scope to a property that does not exist, Mustachio will skip that section. In this way, you can build templates that do not require if/else logic.

To show this, let's use the following model:

{
    "company_name" : "ACME Rockets, Inc.",
    "employees" : [
     { "name" : "Wile E. Coyote", "position" : "Quality Assurance Tester"},
     { "name" : "Road Runner"}
    ]
}

And we update the template:

<ul>
    {{#each employees}}
        <li>
            {{name}} works for: {{../../company_name}}
            {{#position}}as a {{.}}{{/position}}
        </li>
    {{/each}}
</ul>

When we use Mustachio we will produce the following HTML:

<ul>
    <li>Wile E. Coyote works for: ACME Rockets, Inc. as a Quality Assurance Tester</li>
    <li>Road Runner works for: ACME Rockets, Inc.</li>
</ul>

Note that because Road Runner doesn't have a 'position' property, " as a..." is omitted from the output. Also note that we can use . in the Variable Interpolation to reference the model object in the {{#position}} scoped block.

Inverted Groups (or, how to make Placeholders)

Mustachio will skip anything in a template that reference a value that is null, false, or empty (such as an array that has no elements). However, sometimes it's useful to include content specifically when a value is absent from the model, and, of course, Mustachio supports this using "Inverted Groups":

<ul>
{{#each employees}}
    <li>
        {{name}} works for: {{../../company_name}}
        {{#position}} as a {{.}}{{/position}}
        {{^ years_employed}}since who knows when?{{/years_employed}}
    </li>
{{/each}}
</ul>

In the above example, if years_employed is not specified in our template model, and so therefore, since who knows when? will be rendered.

Inverted Groups are a powerful way to provide placeholder text when information is not available, or not applicable.

Content Safety:

Normally, the information you want to include in a template will be simple scalar values, these values typically lack html markup, and are safe to render to browsers as-is. However, if you accept content from untrusted sources that you wish to embed, it's possible that this content could contain unsafe values that could lead to issues when rendered and served in a browser. This is a common "cross-site scripting" attack, and Mustachio is safe by default:

Let's take this model:

{
   "user_submitted_content" : "<script>$.sendUserPasswordToUntrustedWebsite();</script>"
}

And this template:

<div class="user_comment">{{user_submitted_content}}</div>

Mustachio automatically HTML encodes the values that it interpolates, so that, while producing "ugly" content, the output is rendered harmless:

<div class="user_comment"><script>$.sendUserPasswordToUntrustedWebsite();</script></div>

If you need to opt-out of this behavior, Mustachio provides two syntaxes to accomplish this:

{{{ user_submitted_content }}}

and

{{& user_submitted_content }}

Remember that not escaping content creates a security risk if you'll be presenting the template's output in a browser.

Last updated January 19th, 2017

Still need some help?

Our customer success team is here to help!