Eleventy — Using A Layout As A Partial (The Most Useful Things...)

Deniz Akşimşek

Update 2021-02-08: This article mentions things about my website that are no longer true. The technique explained, however, still works fine.

On this website, I have both a Notes page and pages for each individual note. I wanted to use the same template for both, but I ran into an issue: accessing frontmatter data.

In Eleventy, frontmatter data for the current page is merged into the data cascade and made available on the template global scope, whereas collection items have a data property. This made it hard to write templates that work with both the page object and collection items.

Solution

YouTube user Bantu Tu, commenting on Missing Semester: Lecture 3: Editors (vim) (2020)

[…] the most useful things are usually cloaked in an air of nonchalance, even in documentation.

The solution to my problem was right there in the Eleventy docs, staring at me, its description phrased such that it couldn’t possibly be of use to anyone.

Eleventy docs

Also getCollectionItem

For completeness, a getCollectionItem filter is also included that fetches the current page from a collection.

With this filter, all my problems were solved. I prepended the following to my note.njk template (similarly for post.njk):

{%set item = note | d(collections.note | getCollectionItem(page))%}

When using note.njk as a partial, the caller assigns the variable note. When using it as a layout, no such variable will exist and the default (d()) will be used… The beauty of this configuration is that in both situations, item will be a collection item with a data property.

One caveat is that because I’m using this as a partial, I can’t use frontmatter, and therefore can’t set a layout for my layout (maybe I could use template data files…). Instead, I use Nunjucks’ builtin template inheritance.

{%if not note%}
{%extends "base.njk"%}
{%endif%}
...
{%block content%}
{%set item = note | d(collections.note | getCollectionItem(page))%}
...
{%endblock%}

This page accepts Webmentions.