Automatically Building a List of All Posts in Hugo

Published: 2022 April 01

Last edited: 2022 June 04

software development web development static site generator Hugo Hugo theme

Update Note

When this post was originally published, it linked to a dynamic version of the All Posts list page. That page has been retired. Consequently, links to that page have been replaced with a links to a saved static version of that page.

The Challenge

This project is built with Hugo and uses the Minimal Hugo theme.

This post is part of an ongoing effort to tailor the theme over time.

For this post, we’ll look at how to build an automated list of all posts in the /project/content/post/ directory while leaving the existing paginator unaltered.

Hugo allows one list template per section, and since we want to keep the existing paginator, we need to find another way to automatically build that list.

The Process

A web search of the topic didn’t yield any relevant results, so we next turned to asking for direction on Hugo-focused web forums.

A helpful answer came almost immediately, thanks to Bryce Wray. In addition to outlining his approach, he linked to his code and the resulting site map on his webpage.

This article by Kodify.net offered additional guidance for defining filters in Hugo.

Combination, modification, and testing of those techniques formed the basis of the solution for this project.

The Solution

New layout directory and new template file

Since we want list pages for the /project/content/post/ directory to be built using the default list template, we’ll create a separate template in a different directory.

Specifically, we’ll create the new directory /project/layouts/map/ and to that directory we’ll add the file single.html, which contains:

{{ partial "header" . }}

<main>

    <div>{{ .Content }}</div>

    <h5>{{ len (where .Site.RegularPages "Section" "==" "post") }} total posts</h5>
    <h5><a href="/post/">See the paginated list.</a></h5>

    <hr>

    {{ range where .Site.Pages.ByPublishDate.Reverse "Section" "==" "post" }}
      {{ if (ne .Title "Posts") }}
        {{ partial "list-item" . }}
      {{ end }}
    {{ end }}

    <hr>

</main>

{{ partial "footer" . }}

Looking more closely:

<h5>{{ len (where .Site.RegularPages "Section" "==" "post") }} total posts</h5> - provides a count of all pages in the /project/content/post/ directory.

<h5><a href="/post/">See the paginated list.</a></h5> - creates a link to the original paginated list of the posts in /project/content/post/ directory.

{{ range where .Site.Pages.ByPublishDate.Reverse "Section" "==" "post" }} - iterates through pages in the /project/content/post/ directory.

{{ if (ne .Title "Posts") }} - excludes the post list itself (as Wray explains in his answer).

{{ partial "list-item" . }} - uses the list-item partial to output each iterated page (except the post list itself).

We expect that this could eventually be generalized to create more lists of other content in the same directory by extracting the references to post into a variable that is passed to the page. For now, the current version meets the needs of the project.

New content directory and content file

With the new layout directory and template file created, we can now create the content directory and content file that will instantiate the page.

Specifically, we’ll create the new directory /project/content/map/ and to that directory we’ll add the file all-posts.md, which (besides frontmatter) contains only the page title, since all other necessary information is contained in the template:

## All Posts

The Result

With that, Hugo can automatically build a page listing all posts in the /project/content/post/ directory .

Copying Directory Structure With a Bash Script - With Help From ChatGPT AI

Published: 2024 January 22

Backing Up Git Config Values With a Bash Script

Published: 2023 August 25

Backing Up Visual Studio Code (VS Code) Settings and Extensions With a Bash Script

Published: 2022 November 09