Learning Assemble, Step 4 - Data

2014-10-26

In this post we'll look at custom data used by Assemble and Handlebars templates.

  • Page data (YAML Front Matter)
  • Site data
  • Built-in data

Page Data

Assemble provides a way for each page to supply data in the YAML markup at the top of the page, referred to as YAML Front Matter. We have already used this in our pages to specify the page titles.

---
title: "Home"
---
<h1>{{ title }}</h1>
<p>This is the home page</p>

You can use YAML front matter to define arbitrary data for whatever purpose you see fit. The data can be used within the page itself, and is also passed to layouts and partials rendering the page. We've already done that, too, our layout uses the title for the HTML title:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
{{> header }}
{{> body}}
</body>
</html>

Let's try a few experiments with the data.

Create Arbitrary Data

The simplest test is to stick in some arbitrary data and use it in the HTML template.

---
title: "Home"
message: We have lots of cool stuff
---
<h1>{{title}}</h1>
<p>{{message}}</p>

We just moved the message text from the HTML template into the front matter data as 'message', and then referenced the data back in the HTML. You can also see that YAML does not require us to enclose a string in quotes.

Create a Custom List

Let's create a custom list of data in YAML, which we will then use to dynamically create HTML in the page template. This would appear as follows:

---
title: "Home"
message: We have lots of cool stuff
promotions:
 one:
  title: "Promotion 1"
 two:
  title: "Promotion 2"
 three:
  title: "Promotion 3"
---
<h1>{{title}}</h1>
<p>{{message}}</p>
<ul>
    {{#each promotions}}
        <li>{{title}}</li>
    {{/each}}
</ul>

There are a few noteworthy things here:

  • You can see on lines 4 - 10 we specify a list of three promotions in YAML. This is a 'promotions' object, which is itself an array of three objects, each of which has one 'title' property. Indentation nests objects and attributes.
  • We use this array of promotions on lines 15 - 17, in a loop using the Handlebars {{#each}} syntax to create list items for each promotion.
  • Notice on line 16, we use the Handlebars command {{title}} to print the promotion title, this is actually the exact same syntax as we used for the page title on line 12. However, the data context is different. The context provided by the {{#each promotions}} loop makes this possible. I recommend you experiment with this, but come up with a naming convention that makes it clearer to page maintainers which data is which.

You can make as little or as much of your page content render from data as makes sense to you and your design.

Site Data

In addition to the data describing each individual page, you can have global data for your site. The easiest way to do this is to put your data in a JSON or YAML file, then reference that from the Assemble configuration in your Gruntfile. Let's try that.

We'll create a data file, site.json in a new source/data folder. While this uses JSON for contrast, the effect is the same as YAML.

{
    "site": {
        "title": "Awesome Static Site"
    }
}

And then we'll reference this from the Gruntfile (only the assemble task configuration shown):


        assemble: {
            hello: {
                options: {
                    data: 'source/data/*.{json,yml}',
                    layoutdir: 'source/templates/layouts',
                    layout: 'default.hbs',
                    partials: 'source/templates/partials/**/*.hbs'
                },
                files: [
                    { expand: true, cwd: 'source/templates/pages', src: '**/*.hbs', dest: 'output/' }
                ]
            }
        },
...

We added a path to a 'data' directory, where Assemble should read any .json or .yml files in that folder as part of the data model. This makes it easy to add data as you go.

Last, let's use the site title from the default layout as part of the HTML header title, to add consistent site title formatting.

<!DOCTYPE html>
<html>
<head>
    <title>{{title}} | {{site.title}}</title>
</head>
<body>
{{> header }}
{{> body}}
</body>
</html>

We can reference the site title as site.title, showing how the JSON from our file was merged into the data model at the top level. Structuring the data makes it a bit easier to keep all the 'title' attributes separate, for example, and also shows how you can model arbitrarily complex data structures. Go crazy.

Built-In Data

Assemble also exposes a good bit of built-in data to you. Most of it is related to page rendering and file logistics. I plan to go into the built-in data as part of separate posts dealing with page navigation, debugging, and manipulating the data.

For the code, please see the learning-assemble repository on GitHub. The branch step04-data contains the completed code from this post.

Next: Learning Assemble, Step 5 - Page Navigation