Andi Smith

Creating a List of Posts in Assemble

In the previous post, I showed how to get started with Assemble. Now we have created a page and a post, it would be great to display our posts on our homepage. We could manually list our posts within our index page, or we could store them in a data file somewhere. But it would be much better if we could list them dynamically.

Creating a list of posts

Assemble allows us to specify lists of posts and/or pages as collections, which we can then use to loop through and get our content. To specify a collection, we need to edit our Gruntfile.js and add a collections object to our posts:

options: {
  collections: [{
    name: 'post',
    sortby: 'posted',
    sortorder: 'descending'
  }],
  ...

This collection looks for a YAML parameter of post to choose which posts to contain, so we need to add a new value to our file src/content/blog/first-post.md:

---
title: "First!"
posted: 2014-01-28
post: true
---

This is my first post!

This will allow us to identify our blog posts as posts, and keep our pages out of the collection.

With our posts marked up we need to create a loop for our collection. Open up src/bonnet/layouts/page.hbs and include the following code after our closing {{/markdown}} tag:

<ul>
  {{#withSort post 'data.posted'}}
    {{#each this.pages }}
    <li>{{ this.data.title }}</li>
    {{/each}}
  {{/withSort}}
</ul>

Here we are telling Assemble that with our collection 'post' ordered by the date posted, we want to loop through the collection and output the page title.

If you re-run grunt from the Terminal/Command Prompt you should now see a list of a single item on all your pages. Let's add another post at src/content/blog/second-post.md:

---
title: "Second!"
posted: 2014-01-30
post: true
---

This is my second post!

If we re-run grunt again we should see two items in our list. Horrah!

A list is great, but it would be great if users could click our list to go to a blog post.

In an ideal world, we would be able to output the path of the post with {{ this.dest }}, but this path includes the 'dist/' folder and to my knowledge there is no way to remove this through Assemble. Instead, we need to create our first Handlebars helper.

Create a new folder called helpers in your bonnet directory and add a file called helpers.js. Inside, we'll create our first helper:

module.exports.register = function (Handlebars, options) {
  'use strict';

  Handlebars.registerHelper('replaceStr', function (haystack, needle, replacement) {
    if (haystack && needle) {
      return haystack.replace(needle, replacement);
    } else {
      return '';
    }
  });

};

Our helper is called replaceStr and will search haystack for needle and replace it with replacement.

We need to tell Assemble where our helpers live, so in our Gruntfile add the following line to Assemble's options:

helpers: './src/bonnet/helpers/**/*.js',

With these parts completed, we can now add the blog URL to our code:

<li><a href="{{ replaceStr this.dest 'dist' '' }}">{{ this.data.title }}</a></li>

If we re-run grunt now, our index page will now link to our post pages; and our post pages will link to each other. And thus, we have now created a list of posts for our blog that sits on each page.

If you've not been coding, you can access our progress so far by cloning the example repo:

git clone https://github.com/andismith/assemble-blog-template.git
git checkout v2
npm install

Coming Up

I'll be posting a number of shorter tutorials showing how to add extra functionality to your blog starting with adding categories and pagination.

Stay tuned!