Using Mustache with the Play Framework


One of the more interesting stories that came out of our work on Individual Electoral Registration (IER) was our adoption of Mustache, a logic-less templating language.

How it was

The IER project is built using the Play Framework. Play has its own templating language with a syntax mixing Scala and HTML.

After a few months working with Play we found some difficulties:

  1. The template code was hard to read because it often had to include additional Scala code to change the data it was given into the correct format
  2. Even for experienced Scala developers the pseudo-functions embedded in HTML were confusing, difficult to program against and hard to test
  3. Play's built-in controls, used to generate common HTML tags, did not support all the features of HTML5

As an example of 1 and 2, this is the code needed to generate a checkbox:

@input(field, args:_*) { (id, name, value, htmlArgs) =>
    <input type="checkbox" id="@id" name="@name" value="@boxValue" @if(value == Some(boxValue)){checked="checked"} @toHtmlArgs(htmlArgs.filterKeys(_ != 'value))/>

It’s also a real mash-up of HTML and Scala with no clear idea of what you’re looking at. A front-end developer would be unsure what HTML they could change, while the Scala developer is left with a messy function invocation.

As described in 3. it does include the basic things a checkbox needs but is missing lots of other standard HTML5 parameters, eg. ARIA tag. To add them we had to wrap Play helpers in our own which gave us what you see above.

Searching for solutions

A colleague, Edd Sowden, mentioned he had run into similar problems on another project and suggested we try switching to Mustache as they had. We decided to allow one of our developers a day to investigate.

Mustache is supported by most modern languages so it was easy to find a Scala library. The developer involved had enough time to make a working prototype and said that based on this, there was nothing we were doing with the existing language that we couldn't do with Mustache.

Moving to Mustache

We decided to switch to Mustache completely. A plan was put in place to ensure the project lost no momentum.

This was done in four stages:

  1. we did some preparatory work to let us use Play and Mustache templating in parallel
  2. all new pages were written in Mustache, doing the simplest first
  3. when we were enhancing an existing page, we took this opportunity to convert that page to Mustache
  4. stories were written for the remaining pages, and we added a few of these stories to each sprint

This meant by the time we got past stage 2, the whole team had enough experience of using Mustache that it didn’t slow us down.

A quick look at the Play templating approach

Play is built on fairly standard Model-View-Controller patterns. When user input is sent into the Controller Play validates it by passing it into a Form object. The Controller then decides what to do next based on the response, either to return the next page or to send back the current one with validation errors in. When the Controller wants to render a page it passes the Form object to the View.

For example, in the View code below we extract the user's date of birth from the Form object to render it. The Form object returns a Scala Option when queried, which we have to access through Scala functions like getOrElse to ensure the final value is a string:


The Mustache templating approach

Mustache separates logic from the render code. This separation forced us to split our render code into two bits: a Presenter to hold the logic and a Template for the HTML.

The example above is split into the following:

The Presenter queries the Form object to create the ‘dob’ variable.

val dateOfBirth = for(
    day <- form("dobDay");
    month <- form("dobMonth");
    year <- form("dobYear")
) yield {
  s"$day $month $year"
Map("dob" -> dateOfBirth)

This is sent to the Mustache Template to render the page:


Implementing the new structure

By forcing us to separate our logic into distinct worlds Mustache also made us provide a consistent interface to handle communication between those worlds. We settled on the class below as the properties required by HTML input tags in order to render and interact with the server correctly.

case class Field (
    id:String = "",
    name:String = "",
    classes:String ="",
    value:String = "",
    attributes:String = "",
    optionList:List[SelectOption] = List.empty

In Mustache you only render the properties you need so the Field class can be seen as the superset of all properties required to render all types of input tag.

Below we are rendering a block of HTML that handles the user’s National Insurance number. You can see Mustache calling for the nino properties like id, classes and value. The result is a HTML template that contains much less mess and is much friendlier to developers unfamiliar with Scala.

<label for="{{}}" class="visuallyhidden">
    What is your National Insurance number?

<div class="validation-wrapper {{nino.classes}}">
<input type="text" id="{{}}" name="{{}}" value="{{nino.value}}"
               autocomplete="off" class="text  validate nino {{nino.classes}}"
               data-validation-name="ninoCode" data-validation-type="field"
               data-validation-rules="nonEmpty nino" />

For comparison, here’s the template code we were using for the same HTML before we moved to Mustache:

    label = "What is your National Insurance number?",
    labelAttributes = Map('class -> "visuallyhidden"),
    inputAttributes = Map('class -> "nino"), crossField = keys.nino

Useful outcomes

Improved collaboration

By separating the concerns better we found we could work together far easier than before. Previously, any template change would usually require some pair programming. With the new system what you were working on (HTML or Scala) defined where you did that work so we could stay within our specialisms without as much forced overlap.


Our front-end developers found the templates a lot easier to read. Separating the code into distinct layers made it easier to navigate and we no longer had to jump through multiple Play helper templates to figure out what would actually render.

Sharing code

An additional benefit of using Mustache was reuse. Mustache is designed to be language agnostic, so templates used in a Scala project can be reused in  a project written in another language.

This means if you’re using AJAX to update parts of your pages, your server-side application and your client-side code can share the same  templates. The Shared Mustache gem we use on Ruby on Rails projects is a good example of this.

Other useful things such as sharing templates between prototypes and applications also become possible, as well as having HTML you can use across projects. We didn’t get the chance to do these on IER but it’s good to know the latter is possible for the future.


Separating the code for the Presenter of a template from the template itself helped how we test both. We can now test the Scala code using normal unit tests and the HTML template by rendering it and testing our assumptions with different models.


Effect on the size of the code base

Separating everything meant more files in the code base. Play’s helpers had also been generating a lot of the HTML which now had to live in the templates, making them a lot longer. This is a down side we have learnt to live with and given the positives above we felt the trade off was worth it.


We did some basic tests using the Average Load Time Tester Chrome plugin to see if the switch to Mustache had any impact on the time it took to render a page.







Mustache rendered page containing no user input 0.338 0.547 0.547
Mustache rendered page containing user input 0.315 0.539 0.539
Play rendered page containing no user input 0.280 0.523 0.524
Play rendered page containing user input 0.283 0.559 0.560

Over 100 renders the original Play templating language was slightly faster to render a page where the fields contained no user input. However, when the fields contained user input, Mustache was actually faster. These aren't comprehensive tests but were enough to calm any fears we had when switching.

This post was written by Michael Allen and Tom Byers.


  1. Comment by Josh Goodwin posted on

    I'm curious to know which version of Play was used to get those performance numbers - apparently ( 2.3 has some big templating performance improvements. (Either way, Mustache clearly isn't slow, of course.)

    • Replies to Josh Goodwin>

      Comment by Michael Allen posted on

      Hi Josh, We've been using Play 2.2 and are eyeing Play 2.3 for it's SBT-Web asset pipeline improvements.

  2. Comment by Alexander posted on

    Did you use one of existing SBT-based solution? Or it is you own implementation?


Leave a comment

We only ask for your email address so we know you're a real person