The Postmark team cares deeply about creating fantastic experiences for our customers. We put a lot of thought into each feature that we build, and balance many factors to make sure we focus our efforts on the aspects of our products that we think can provide the best outcomes for our users.

When we started planning the Templating experience, we had the following goals for the feature:

An approachable experience that felt natural to developers and designers coming from multiple platforms.

An editing experience that didn’t require many context switches between the template editing environment and an external code editor.

A rock-solid, safe, Templating language with a good balance of power and simplicity.

To achieve these goals, we looked at a numberofoptions including the Templating features provided by some of our competitors. After reviewing the options, the Mustache language felt like the best fit with what we wanted to accomplish.

If you’ve ever generated dynamic HTML, you’ve had to deal with weaving your dynamic data in with static elements. Depending on the language and tools you use, this can be a frustrating experience. One big factor for this frustration is the constant switching between markup, code, and browsers (a problem that is compounded when you create emails that have both Text and HTML bodies). We wanted to avoid the need to switch between editing environments when authoring templates; This requires a little bit of magic.

We extended Mustache to add something called “each” - a feature which is able to detect the dynamic content you’re using in your Template’s HTML, Text, and Subject, and to provide an example JSON model that you can use when integrating the Postmark Templates into your applications.

It is possible to loop over an array of values using basic Mustache:

{{#products}}{{product_name}}{{/products}}

However, for us to detect that ‘products’ is going to be used as a collection, we need a hint. We added the “each” keyword to Mustachio, which looks like this:

{{#each products}}{{product_name}}{{/each}}

Adding this tiny feature allows a template author to completely design an email in our editor, and then use the model we provide as a reference when leveraging the template in an application’s code. If your experience is anything like mine, this is a significantly streamlined process.

Adding Model Inference for our case was not a particularly difficult Engineering problem, but we think it is a powerful helper, and was missing from all of the templating languages we considered.

The second feature we added to Mustachio is called “Complex Keys.” Many derivatives of Mustache have support for complex keys, but here’s an example of the problem this feature solves (basic Mustache that will render a value 2 levels down):

{{#person}}{{#address}}{{line1}}{{/address}}{{/person}}

And here’s the same thing in Mustachio:

{{person.address.line1}}

This is a significant savings in markup, which makes the template easier to read.

In addition, we wanted to make sure you didn’t need to repeat elements of your data model, so we added a way to traverse “up” your model:

{{#each products}}
Thanks for your order of {{ . }} made on {{ ../order_date }}
{{/each}}

Without the ability to traverse “up,” the model that would be required to make this same content in Mustache ends up being pretty redundant (Note that the key for the 'product_name’ would also need to be changed from ’.’):

Now that I’ve discussed the features we added, let’s talk a little bit about what we left out. If you’re already familiar with Mustache, you’ll know that we did not include “partials” or “helpers” in our initial release of Postmark Templates.

There are two major reasons for this:

The editing experience that supports partials is substantially harder to approach for users that are new to the feature, because they would need to understand a larger amount of internals on how templates are referenced and stored. Partials/helpers immediately demand more knowledge of how everything works, and a more complex UI to navigate between components of a template.

The ability for users to manage changes in templates is harder, because changes to partials can significantly (and indirectly) alter the final appearance of content that is created from a template.

We know that some users will want to use partials to have greater code reuse, but we also know that many emails are “one off” and change infrequently. As we learn more about how our customers want to use the Postmark Templates feature, we plan on enhancing it accordingly.

There are many libraries out there that have already implemented Mustache. Each of these projects vary substantially in quality and scope. So, why wouldn’t we just fork one of those projects and make our changes? There are a few reasons we chose to build our own:

Mustachio provides features that enhance the Postmark Template experience. #

When appropriate, our team is perfectly satisfied with leveraging external, general-purpose, components. For example, our .net code relies upon JSON.net extensively. In that case, the way an application does JSON Serialization is not the application’s differentiator, and it’s fairly simple to swap one serialization library for another.

If we were to use an “off-the-shelf” language for Postmark Templates, we would be “outsourcing” the implementation for a component that can make the Postmark Template experience awesome. We know that customers are concerned with lock-in, so we put a lot of thought into adding only a few key features, this makes converting templates to or from Mustachio an easy process, if a customer ever decides to use another Email Service Provider. We also made Mustachio Open Source, so that the templates can be leveraged in other applications.

In a perfect world, we’d all have every feature we could hope for. In the real world, we know that all features are a balance of many limited resources. If we selected an off-the-shelf component, we would need to be prepared to support many features, and the added complexity in our codebase. We would also need to be prepared to handle the latent bugs in an off-the-shelf solution, .

By constraining our language to the right feature set, we ensure that we can focus our energy on making sure those features are defect free.

Each of us is proficient in C# and one or two other languages. Limiting most of our development to a few target languages does a few things:

Reduces operational complexity.

Increases the “lottery factor.” (This is often called “bus factor,” but we’re positive people)

Shares code “ownership” among the entire team.

We’re happy to leverage multiple tools/languages when there’s an obvious best-of-breed option. However, more consideration is required when those options do not match our skill sets; Anything that doesn’t run on the .net or Rails platforms need to overcome the drawbacks of added operational complexity, and the limitations on which team members can fix those components when they break.

Therefore, our ideal template language solution needed to be in written in .net or Ruby. Further, the Postmark backend is mostly .net, so offloading to a .net service is preferred to running an Ruby process.

Software Engineering is a complex process that requires careful consideration for time, cost, and human factors. In our case, we knew that a great templating language was an invariant requirement of building and maintaining our new Templating API for years to come. We might have shortened development time by offloading the language work to an external library, but we felt that the investment in the core component of this feature set was justified.

All of the factors above led us to our solution of building a focused, C#, template parser. We think Mustachio is a great result, and we hope you can see the thought and effort that went into building it, when you use Postmark Templates.