Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
314 lines (265 sloc) 9.97 KB
title date category summary tags
Working with Collections
Collections are a key concept of Eleventy, but they confused me at first. So I looked at the source to figure out how collections work.

Eleventy uses collections to group posts according to various criteria. A collection might consist of articles in a series. Another collection could be of posts about books. A third could be all the posts in a particular directory.

Eleventy gives you two ways to create collections:

Tag-based collections

Pages that share a tag are in the same collection. A template with the following front matter would generate pages in the collections books and reviews.

{%- raw -%}
title: Finding Oz
category: Culture
- books
- reviews
. . .
{% endraw %}

Within a template collections are accessed by name as properties of the global collections object.

{%- raw -%}
  The title of this page is:
  {{ collections.books[0].data.title }}
{% endraw %}

Collections are usually used in loops to iterate over each item in the collection.

{%- raw -%}
{% for post in collections.books %}
  {{ }}
  {{ post.url }}
  {{ }}
  {{ }}
  {{ }}
{% endfor %}
{% endraw %}

The collections object itself looks like this:

  "all": [...],
  "nav": [...],
  "books": [
      "inputPath": "./src/articles/",
      "outputPath": "_site/articles/finding-oz/index.html",
      "fileSlug": "finding-oz",
      "data": {...},
      "date": "2009-08-07T13:52:12.000Z",
      "url": "/articles/finding-oz/",
      "templateContent": "<p>As with most books ... much about The Wizard of Oz</li>\n</ul>\n",
      "template": {...}
  "programming": [...],

Each property is an array of collection item objects (the doc also calls them template objects). The special collection all is an array of all of the page objects that Eleventy generates.

Property Description
inputPath Path to this file including the input directory.
outputPath Path to the rendered file.
fileSlug Short name from the file name. There are rules.
data Data from the front matter of the rendered page. The global variables available to each page.
date The date of this file in UTC. There are rules.
url Path to this content. Doesn't include protocol or host.
templateContent The rendered content, not including any layout wrappers.
<p>As with most books ... much about The Wizard of Oz</p>
template All sorts of data parsed out of the template. Things like the Eleventy configuration, markdown engine setup, and lots of stuff we probably shouldn't rely on.
collection item properties

!!! Implementation: How a tag becomes a collection

getTaggedCollectionsData() is the function that turns tags into collections.

async getTaggedCollectionsData() {
  let collections = {};
  collections.all = this.createTemplateMapCopy(
  debug(`Collection: collections.all size: ${collections.all.length}`);

  let tags = this.getAllTags();
  for (let tag of tags) {
    collections[tag] = this.createTemplateMapCopy(
    debug(`Collection: collections.${tag} size: ${collections[tag].length}`);
  return collections;

getTaggedCollectionsData() gets called in TemplateMap.cache() which is where Eleventy builds the collections. !!!

Custom Collections

In addition to the collections built from tags, you can use addCollection() in your .eleventy.js configuration file to create your own collections.

For example, this is how to create a collection called articles made up of pages generated from templates in the directory src/articles/:

  collection => collection
    .filter(item => item.url
                 && ! item.inputPath.includes('index.njk')
                 && item.inputPath.startsWith('./src/articles/')))

addCollection() takes two arguments:[^addcollection]

  • the name of the collection (a string)
  • a function that takes a collection as an argument.

[^addcollection]: addCollection() doesn't actually do anything other than to associate the collection-building function with the collection name. The collection-building function itself is called later in getUserConfigCollectionsData().

  addCollection(name, callback) {
    name = this.getNamespacedName(name);

    if (this.collections[name]) {
      throw new UserConfigError(
        `config.addCollection(${name}) already exists. Try a different name for your collection.`

    this.collections[name] = callback;

You might think that the collection parameter is an array of template objects like the tag-based collections object. Instead, this parameter is an instance of a TemplateCollection, which is derived from Sortable, and looks like this:

  "items": [
    { ... },
    . . .
    { ... }
  "sortFunctionStringMap": { ... },
  "sortAscending": true,
  "sortNumeric": false

Its items property is an array of all the template objects. It's the same as collections.all. You don't want to access the items directly like this: collection.item[n]. Instead use the following methods to get the items.

Method Description
getAll() Gets all of the items in arbitrary order.
getAllSorted() Gets all of the items in order.
getFilteredByTag(tagName) Get all of the items with a specific tag.
getFilteredByGlob(glob) Gets all of the items whose inputPath matches one or more glob patterns.
[collection api methods]

The items are almost the same as the ones in the tag-based collections. In tag-based collections, items have templateContent. In addCollection() collections, items have _pages. I don't know why.

You can use addCollection() to create collections of pages. Since Eleventy 0.5.3, you can use it to create collections or arbitrary objects.

For instance, this is how you'd make a collection that consists of an array of all the category properties:

module.exports = function(collection) {
  let catSet = new Set()

  collection.getAllSorted().forEach(item =>
        typeof === "string"
    &&  catSet.add(

  return [...catSet]

!!! Implementation: How custom collections get built

getUserConfigCollectionsData() is the function that calls addCollection()'s callback.

async getUserConfigCollectionsData() {
  let collections = {};
  let configCollections =
    this.configCollections || eleventyConfig.getCollections();
  for (let name in configCollections) {
    let ret = configCollections[name](this.collection);

    // work with arrays and strings returned from UserConfig.addCollection
    if (
      Array.isArray(ret) &&
      ret.length &&
      ret[0].inputPath &&
    ) {
      collections[name] = this.createTemplateMapCopy(ret);
    } else {
      collections[name] = ret;

      `Collection: collections.${name} size: ${collections[name].length}`
  return collections;

getUserConfigCollectionsData() gets called in TemplateMap.cache() which is where Eleventy builds the collections. !!!

You can’t perform that action at this time.