Templates

Templates in Maizzle contain the body of your email templates.

They're made up of two distinct sections:

  1. Front Matter
  2. Your HTML

Front Matter

Templates can define variables and even override existing ones in your config, through YAML-style Front Matter.

It looks like this:

---
title: "Please confirm your email address"
---

Front Matter variables are available under the page object, which means you can render them in your Templates, like this:

<p>{{ page.title }}</p>

Extending Layouts

A Template can extend a Layout using the <extends> tag:

---
preheader: The Weekly Newsletter
---

<extends src="src/layouts/main.html">
  <!-- Add block tags here -->
</extends>

The path provided in the src="" attribute must be relative to the path in build.layouts.root from your config.

How Extending Works

When a Template <extends> a Layout, a <block> tag with an identical name="" attribute is searched for in the Layout being extended.

Each matching tag found in the Layout will be replaced with the contents of its corresponding <block> tag from the Template.

Extending Templates

A Template can also extend another Template.

For example, imagine src/templates/first.html :

<extends src="src/layouts/main.html">
  <block name="template">
    Parent
    <block name="button">Child in first.html</block>
  </block>
</extends>

We could then extend it in src/templates/second.html :

<extends src="src/templates/first.html">
  <block name="button">Child in second.html</block>
</extends>

The body of second.html would be:

Parent
Child in second.html

Of course, if we use a template block in second.html, then we overwrite everything in first.html:

<extends src="src/templates/first.html">
  <block name="template">
    Second
    <block name="button">Child in second.html</block>
  </block>
</extends>

Result:

Second
Child in second.html

Blocks

For a Layout to render a Template's body, that body must be wrapped in a <block> that has the same name="" attribute in both the Template and the Layout.

In the Starter, we named it template:

<block name="template">
  <!-- email body -->
</block>

Everything inside that <block> will be output into the Layout that the Template extends, wherever a <block name="template"></block> is found.

Multiple Blocks

Your Templates can use as many blocks as you need.

For example, the Starter uses a head block in its main Layout, allowing you to inject additional code into the <head> of you HTML email, right from the Template.

Basic Example

Here's a very basic Template example:

<extends src="src/layouts/main.html">
  <block name="template">
    <table>
      <tr>
        <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
      </tr>
    </table>
  </block>
</extends>

Expressions

Maizzle uses posthtml-expressions, allowing you to access variables from your environment config or from the Template's Front Matter inside curly brace syntax:

<extends src="src/layouts/main.html">
  <block name="template">
    You ran the `maizzle build {{ page.env }}` command
  </block>
</extends>

Running maizzle build production would render this:

You ran the `maizzle build production` command

You can even use some JavaScript expressions within curly braces:

<extends src="src/layouts/main.html">
  <block name="template">
    doctype is {{ page.doctype || 'not set' }}
    this email {{ page.env === 'production' ? "is" : "isn't" }} production ready!
  </block>
</extends>

Unescaping variables

By default, special characters are escaped:

---
markup: '<strong>Bold</strong>'
---

<extends src="src/layouts/main.html">
  <block name="template">
    {{ page.markup }}
    <!-- &lt;strong&gt;Bold&lt;strong&gt; -->
  </block>
</extends>

If you need to render values exactly as they are, so that maybe markup is interpreted, use triple curly braces:

---
markup: '<strong>Bold</strong>'
---

<extends src="src/layouts/main.html">
  <block name="template">
    {{{ page.markup }}}
    <!-- <strong>Bold</strong> -->
  </block>
</extends>

Ignoring

Other templating engines, as well as many ESPs also use the {{ }} syntax.

If you want to output the curly braces as they are, so you can evaluate them at a later stage, you have two options:

  1. Use @{{ }}

    The Blade-inspired syntax is useful for one-offs, where you need to ignore a single expression. The compiled email will render {{ }} without the @.

  2. Use the <raw> tag

    This is useful if you have multiple lines containing {{ }} and want to ignore them all in one go:

    <raw>
      Nostrud laboris sunt Lorem {{ var1 }} cupidatat fugiat tempor ad tempor anim.
      Veniam non sit {{ var2 }} ipsum ad qui.
    </raw>

    The <raw> tag will be removed in the final output, but the curly braces will be left untouched.

Ignoring expressions inside Front Matter

Due to the way Maizzle works to enable expressions inside Front Matter, if you need to ignore an expression there you will also have to ignore it in the Layout or Template where you are using it.

For example, in the Template's Front Matter:

---
title: "Weekly newsletter no. @{{ edition_count }}"
---

In the Layout:

<if condition="page.title">
 <title>Weekly newsletter no. @{{ edition_count }}</title>
</if>

This is required because Maizzle first evaluates expressions in Front Matter and then it evaluates them again in the resulting HTML, meaning it will basically evaluate your expression twice.

Options

You can configure posthtml-expressions in your config.js:

module.exports = {
  build: {
    posthtml: {
      expressions: {
        // posthtml-expressions options
      }
    }
  }
}

Besides configuring templating tag names, here you can also pass other options to the plugin. For example, you could change the default expression delimiters from {{ }} to something like [[ ]]:

module.exports = {
  build: {
    posthtml: {
      expressions: {
        delimiters: ['[[', ']]']
      }
    }
  }
}

You'd now use variables or expressions like this:

<extends src="src/layouts/main.html">
  <block name="template">
    doctype is [[ page.doctype || 'not set' ]]
  </block>
</extends>

See all posthtml-expressions options.

Archiving

Maizzle will only compile templates found in path(s) you have defined in build.templates.source, and which use the extension defined in build.templates.extensions.

If you create a lot of emails, your builds can start to slow down, since all templates are rebuilt every time you run the build <env> command or when developing locally and making changes to a Layout or Component.

You can archive Templates in two ways:

  1. Move them to a directory outside the one defined in build.templates.source, so they don't get copied over to the destination directory (recommended).
  2. Change their file extension to something that is not defined in build.templates.filetypes. They'll just be copied over to the destination, Maizzle will not try to compile them.