List documents by date in DocPad

DocPad is a fantastic tool to generate static websites. It covers the same feature set as Jekyll, but is probably better suited for people who generally prefer to swap out Ruby for node.js.

Much like Jekyll, getting up-and-running with DocPad is pretty simple. DocPad supports a rich API, as well as a number of convenient helper methods that illustrate how powerful the tool really is.

Unfortunately, the examples for doing simple data-binding (binding JSON, or some other data source to markup) were a little sparse. I had to Google quite a bit to get a relatively simple scenario to work. Luckily, once I had ironed out the kinks, it worked like a charm.

Here's my use case:

Retrieve a list of files in a particular source directory and display links to these files (with corresponding meta-data) in descending order according to date.

Directories

So, my source directory looks roughly like this:

|-documents
|---news
|-----articles
|-------my-news-item.html.eco

The idea being, that a number of news articles will be added to /articles so that the end result is something like /news/articles/my-news-article/.

Documents

In this use case, I created a number of .html documents to be included as articles. If you want to make use of DocPad's helpers and templating (as I do in this example), you'll have to properly append .eco to each filename. The reason for this is because DocPad utilises eco, a library that allows you to embed Coffeescript logic in markup.

Before we move on to the DocPad config and queries, we need to add meta data to each of the our articles. Here's an example:

---
title: "My News Item"  
layout: "default"  
isPage: true  
date: 1987-06-21  
description: Here's a nifty description of this item  
---

<!DOCTYPE html>

In this example, we added two custom properties: date and description. DocPad allows you to add pretty much anything as meta data.

DocPad config

Now that we've got directories and files to query, let's jump into the docpad.coffee file. Here's my configuration:

moment = require('moment');

docpadConfig = {  
  ignoreCustomPatterns: "*hidden*",
  templateData:
    // Data
    articles_news: -> @getCollection('documents').findAllLive({relativeOutDirPath: 'news/articles'}).toJSON()

    // Helpers
    postDatetime: (date, format = "DD/MM/YYYY") -> return moment(date).format(format)
    getArticlePath: (section, fileName) -> return "/#{section}/articles/#{fileName}"
}

# Export the DocPad Configuration
module.exports = docpadConfig  

Some notes:

  • moment.js is included to properly handle date formatting during rendering. Note: DocPad automatically converts date strings into ISO8601 dates.
  • articles_news is a function defined in DocPad's templateData namespace. This means that any variable declared in an .eco file that's prefixed with @ references this namespace directly.

Here's an example of the markup:

<ul class="pure-menu-list align-left">  
   <% for article in @articles_news() : %>
   <li class="pure-menu-item side-menu-item">
      <a href="<%- @getArticlePath('news', article.outFilename) %>" class="pure-menu-link">
      <span class="article-date"><%- @postDatetime(article.date) %></span>
      <br>
      <span class="article-title"><%- article.description %></span>
      </a>
   </li>
   <% end %>
</ul>  

That's it. Again, hopefully this helps someone.