Hackerman's Hacking Tutorials

The knowledge of anything, since all things have causes, is not acquired or complete unless it is known by its causes. - Avicenna

Feb 14, 2016 - 3 minute read - Comments - Migration to Hugo Not Security

Archive Page in Hugo

This is a re-hash of my answer on Hugo forums about creating a custom archive page. You can see the answer here.

Creating a custom archive page in Hugo is pretty simple. I think there are better ways to do this but this works as of version 0.15.

Content types in Hugo are determined in two ways:

  • Directory structure: For example in my blog, every blog post is in content\post and as a result is of type post. The template used to create each post is in themes\Hugo-Octopress\layouts\post\single.html. You can learn more by reading the Content Types section in Hugo documentation.

  • Through a variable named type in front matter. For example type: mycustomtype in the front matter will assign this type to the page. In this case, the page can be anywhere in the content directory and the directory structure is irrelevant. It's also possible to set the relative URL of the page with the url frontmatter variable.

To create an archive page, create a Markdown file in content and create a new type for it. The name of the file is going to determine the path of the generating file. If the file is named content\archive.markdown then it will be located at baseurl/archive/ in my case. The name of the type does not have any effect on the path. Here's what I have in this file:

content\archive.markdown
---
title: "Archive page"
type: myarchivetype
---
Blog archive

Another way to assign a URL to a page is through the url parameter in front matter. This overrides the path set before.

markdown file with url tag
---
title: "Archive page"
type: myarchivetype
url: "/path/to/archive/"
---

This makes the page to appear in baseurl/path/to/archive/.

The template used to generate this file is going to be located in layouts\myarchivetype\single.html (or themes\theme-name\layouts\myarchivetype\single.html). I have the following code in my this file:

{{ partial "header.html" . }}
<div id="main">
  <div id="content">
    <div>
      <article role="article">
        <header>
          <h1 class="entry-title">
            {{ .Title }}  <!-- title, in this case it will be "Archive page" -->
          </h1>
        </header>
        <div id="blog-archives" class="category">
          {{ .Content }} <!-- content of the markdown file. note that inside the range .Content will point to each page's content -->
          {{ range (where .Site.Pages "Type" "post") }}
          <h2>
            {{ .Date | dateFormat "2006"}} <!-- print publish year -->
          </h2>
          <article>
            <h1>
              <a href="{{ .Permalink }}" title="{{ .Title }}">{{ .Title }}</a>
            </h1>
            <time>
              <span class="month">{{ .Date | dateFormat "Jan" }}</span> <!-- print publish month -->
              <span class="day">{{ .Date | dateFormat "2" }}</span> <!-- print publish day -->
            </time>
              <!-- if you want pages summary you can print it here {{ .Summary }} -->
          </article>
          {{ end }}
        </div>
      </article>
    </div>
    {{ partial "sidebar.html" . }}
  </div>
</div>
{{ partial "footer.html" . }}

Notice that I have used {{ range (where .Site.Pages "Type" "post") }} to only iterate through pages of type post. You can use {{ range .Site.Pages }} to go through every markdown file. You can also use pagination (similar to the index page).

The {{ .Content }} variable points to the content of the archive.markdown page outside the range and to each page's content inside it.

You can see it in action at Archive page.