Featured image of post Adding Support for Post Series

Adding Support for Post Series

Learn how to create a post series in Hugo, with detailed implementation steps and custom styling tips.

My first few posts have been small, standalone posts, but I wanted to write a few posts about something a bit more in-depth. I started looking at how to create a series and it turns out that Hugo doesn’t support this out-of-the-box without some additional work.

Adding Support for Post Series

After a quick search on Google I came across the blog post ‘Hugo - Create a Post Series’ by Justin James.

In that article Justin provides the snippet of code that is needed to get this working along with a really detailed explanation of what the code is doing. I’ll include the code for reference, but for a detailed explanation of what it’s doing, head over to Justin’s blog.

Implementation

The actual HTML that will get rendered on the page, showing all of the posts that belong to a given series, is contributed by something called a ‘partial’. According to the Hugo documentation, partials are “are smaller, context-aware components in your list and page templates that can be used economically to keep your templating DRY.”

  1. To create our own partial, we first need to create a new file called layouts/partials/series.html.

  2. That file should contain the following code:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    {{ if .Params.series }}
    <div class="series">
      <h3>This article is part of a series.</h3>
      <ul class="list-group">
        {{ range $num,$post := (index .Site.Taxonomies.series (index
        .Params.series 0 | urlize)).Pages.ByDate }} {{ if eq $post.Permalink
        $.Page.Permalink }}
        <li class="list-group-item active">
          Part {{ add $num 1 }}: {{ $post.Params.title}}
        </li>
        {{ else }}
        <li class="list-group-item">
          <a href="{{$post.Permalink}}">
            Part {{ add $num 1 }}: {{ $post.Params.title}}
          </a>
        </li>
        {{end}} {{end}}
      </ul>
    </div>
    {{end}}
    
  3. To make use of the partial we need to add it to the layouts/partials/article/article.html file. Here you can see it being added on lines 4 and 8. This will show the list of posts in the series before and after the content of the current post. Showing it at the beginning tells the reader that this is one post within a series. Showing the list again at the end of the article will make it easy for the reader to get to the next post, without having to scroll back up to the top of the page.

    1
    2
    3
    4
    5
    6
    7
    
    <article class="{{ if .Params.image }}has-image {{ end }}main-article">
      {{ partial "article/components/header" . }} {{ partial "series.html" . }}
      {{ partial "article/components/content" . }} {{ partial "series.html" . }}
      {{ partial "article/components/footer" . }} {{ if or .Params.math
      .Site.Params.article.math }} {{ partialCached
      "article/components/math.html" . }} {{ end }}
    </article>
    
  4. In order to identify posts as being part of a series, we need to specify the series attribute in each of the posts’ front matter.

    1
    2
    3
    4
    5
    
    ---
    title: "Title of the blog post"
    date: 2023-09-09T20:24:08+01:00
    series: ["Name of series"]
    ---
    
  5. Finally, we need to define “series” as a taxonomy in the config.toml file.

1
2
3
4
[taxonomies]
tag = "tags"
category = "categories"
series = "series"

In my blog I’m also using the default taxonomies of tags and categories. When adding a custom taxonomy, in our case series, you must also specify the default taxonomies if you want to keep them. You can read more about how to configure taxonomies in the official Hugo documentation.

Styling

At this point I found that I didn’t have the nicely styled table that Justin had in his example. Instead, I found I had this:

Unstyled list of posts in the series

In order to make it look better we have to add some custom CSS to the assets/scss/custom.scss file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.series h3 {
  color: var(--card-text-color-main);
}

.series {
  padding-left: 30px;
  padding-right: 30px;
}

.list-group {
  padding-left: 0;
  margin-bottom: 20px;
}

.list-group-item {
  position: relative;
  display: block;
  padding: 10px 15px;
  margin-bottom: -1px;
  background-color: transparent;
  border: 1px solid var(--table-border-color);
}

.list-group-item.active {
  background-color: #339fff;
  border-color: #339fff;
  color: #fff;
  font-weight: bold;
}

Some points worth noting about the above: Lines 2 and 21 refer to CSS variables because the theme I’m using on the blog supports light and dark modes, so we need the heading and the table to respond accordingly. Likewise, the background colour of each item in the list is set to be transparent to allow the theme-specific background colour to show through.

With the CSS in place we now have something that looks a lot better.

Styled list of posts in the series

After all that, we now have the ability to link a series of posts together and display that information to reader. I think that’s enough yak shaving for one evening and now it’s time to get on writing the actual series of posts I originally set out to write.