Generating Archive Pages with Hugo

Archive Page
Archive Page

In the absence of a search engine — an Check out my posts archive page. page is a simple way to find older articles quickly. Here is a quick and dirty way to create multiple archive pages with Hugo.

There are a few requirements. The archive pages should be a bit modular. We should be able to just drop an archive.md file into any folder within the content directory and generate a single archive page for that topic.

hugo
└── content
   ├── posts
   │   └── archive.md
   └── projects
       └── archive.md

We should be able to generate clean slugs. Hugo makes that URLs are typically generated according to the file directory structure. The slugs for each archive page topic would be of the form /posts/archive and /projects/archive.

We could also take a more pragmatic approach by using the following file directory structure which results in slugs like /archives/posts or /archives/projects.

hugo
└── content
   └── archives
      └── posts.md
      └── projects.md

The content of each archive page will be determined by the parameters within the front matter, particularly the layout parameter. The front The front matter is the only data in this file actually. content in posts/archive.md will contain the needed parameters to generate that page.

---
title: "Posts Archive"
layout: archive
hidden: true
type: posts
summary: This page contains an archive of all posts.
---

The layout parameter will reference the template layouts/_default/archive.html to render a single archive page. That template file is shown below.

{{ define "main" }}
<section class="section is-fullheight">
  {{ $type := .Type }}
  {{ $.Scratch.Set "count" 1 }}

    {{ range (.Site.RegularPages.GroupByDate "2006") }}
      {{ if and (gt .Key 1) (gt (where .Pages "Type" $type) 0) }}

        {{ range (where .Pages "Type" $type) }}
          {{ if (eq ($.Scratch.Get "count") 1) }}
            {{ $.Scratch.Set "count" 0 }}
            <h1 class="title is-4 has-text-weight-normal">{{ .Date.Format "2006" }}</h1>
          {{ end }}
        {{ end }}

        {{ $.Scratch.Set "count" 1 }}

          <ul class="article__list">
          {{ range (where .Pages "Type" $type) }}
            {{ if (ne .Params.hidden true) }}
              <li>
                <a class="is-block" href="{{ .RelPermalink }}">
                  <span class="has-text-grey-dark">{{ .Date.Format "02 Jan" }}</span> — {{ .Title }}
                </a>
              </li>
            {{ end }}
          {{ end }}
          </ul>

    {{ end }}
  {{ end }}
</section>
{{ end }}

This template groups all posts for a particular topic by year and orders them by the month, taking into account the type parameter from the front matter of archive.md. Note the use of the .Scratch .Scratch allows us to create a sort of scratchpad for variables. Is this the best way to set up a boolean variable? Who knows … There is most likely a much cleaner The count variable ends the iteration early and grabs the year once before displaying the article titles. The first function would have been a better choice. but this is good enough.

There are quirks when implementing an archive page as a single post. We may want to adjust the RSS and pagination templates to hide additional data produced by an archive page with the hidden: true attribute.