Creating a List of Direct Child Pages in Eleventy

Rendering a list of the current page’s subpages in Eleventy using a Liquid template, a WebC component, or an Eleventy Shortcode.

Contents

Introduction

This website uses index pages that provide a list of direct child pages. To do so, it leverages eleventyNavigation together with keyparent relations set up in the front matter. The list of subpages can be rendered to HTML using Liquid code, a WebC component, or an Eleventy Shortcode written in JavaScript.

Liquid Template

The Liquid code below compiles the list of child pages for the current page. The title and description are taken from each page’s front matter; the md filter then renders the Markdown syntax to HTML. This code can be placed in a separate file (partial) and included using the Liquid include tag:

{%- assign navPages = collections.all | eleventyNavigation: eleventyNavigation.key -%}
{%- if navPages.size > 0 %}
<dl>
  {%- for child in navPages %}
  <dt><a href="{{ child.url | url }}">{{ child.data.title | md }}</a></dt>
  <dd><p>{{ child.data.description | md }}</p></dd>
  {%- endfor %}
</dl>
{% endif -%}

Eleventy Shortcode

An alternative approach is to define an Eleventy shortcode. Because front matter data is not available to shortcodes, it must be passed explicitly. The listing below shows the implementation of the subpagesIndex shortcode, which accepts the nodes and the key:

eleventyConfig.addShortcode('subpagesIndex', async function (nodes, key) {
  const eleventyNavigation = eleventyConfig.getFilter('eleventyNavigation');
  const subpages = eleventyNavigation(nodes, key);
  if (subpages.length > 0) {
    const md = eleventyConfig.getFilter('md');
    const url = eleventyConfig.getFilter('url');
    let subpagesHTML = '';
    subpages.forEach((page) => {
      subpagesHTML += `\
  <dt><a href="${url(page.url)}">${md(page.data.title)}</a></dt>
  <dd><p>${md(page.data.description)}</p></dd>\n`
      ;
    });
    return `<dl>\n${subpagesHTML}</dl>\n`;
  }
});

The shortcode can be used in a Liquid template as follows:

{% subpagesIndex collections.all, eleventyNavigation.key %}

WebC Component

The following example illustrates a solution using a WebC component to render a list of subpages for the current page. The subpages-index.webc file must be placed in the _components directory at the project root:"

<script webc:setup>
const currentKey = getCollectionItem(collections.all).data.eleventyNavigation.key;
const subpages = eleventyNavigation(collections.all, currentKey);
</script>
<dl webc:if="subpages.length > 0">
  <x webc:for="page of subpages" webc:nokeep>
  <dt><a :href="url(page.url)" @html="md(page.data.title)"></a></dt>
  <dd><p @html="md(page.data.description)"></p></dt>
  </x>
</dl>

Because the eleventyNavigation front matter entry is shadowed by the eleventyNavigation filter, the current page must be retrieved from the collection to access its front matter data. Rendering the dt and dd elements together for each subpage requires wrapping them in a placeholder element that holds the webc:for attribute.

The subpages-index element can then be added to a layout or template:

<subpages-index></subpages-index>