Using Atom With Hugo

Hugo

Introduction

While Hugo is a great static site generator, it can sometimes be difficult to set it up to use Atom feeds instead of RSS feeds. Here’s how to do it.

Configuring Hugo

Add this bit of configuration to your config.toml.

NOTE: (Site.)author.name is required for the template to generate a valid Atom 1.0 Feed.

NOTE: You might want to modify the outputs section if you want to include RSS and/or other output formats. Here’s a link to the relevant Hugo documentation.

[author]
        name = "John Doe"

[mediaTypes."application/atom+xml"]
  suffixes = ["atom"]

[outputFormats.ATOM]
  name = "ATOM"
  mediaType = "application/atom+xml"
  baseName = "feed"
  rel = "alternate"
  isPlainText = false
  isHTML = false
  permalinkable = false

[outputs]
  home = ["HTML", "ATOM"]
  section = ["HTML", "ATOM"]
  taxonomy = ["HTML", "ATOM"]
  term = ["HTML", "ATOM"]

Adding the Template

Add the following template as layouts/_default/list.atom:

{{ printf `<?xml version="1.0" encoding="utf-8"?>` | safeHTML }}
{{/* ref: https://validator.w3.org/feed/docs/atom.html */}}
<feed
  xmlns="http://www.w3.org/2005/Atom"
  {{ with site.LanguageCode }}xml:lang="{{ . }}"{{ end }}>
  <generator uri="https://gohugo.io/" version="{{ hugo.Version }}">
    Hugo
  </generator>
  {{- $title := site.Title -}}
  {{- with .Title -}}
    {{- if (not (eq . site.Title)) -}}
      {{- $title = printf `%s %s %s` . (i18n "feed_title_on" | default "on") site.Title -}}
    {{- end -}}
  {{- end -}}
  {{ printf `<title type="html"><![CDATA[%s]]></title>` $title | safeHTML }}
  {{ $output_formats := .OutputFormats }}
  {{ range $output_formats -}}
    {{- $rel := (or (and (eq "atom" (.Name | lower)) "self") "alternate") -}}
    {{ with $output_formats.Get .Name }}
      {{ printf `<link href=%q rel=%q type=%q title=%q />` .Permalink $rel .MediaType.Type .Name | safeHTML }}
    {{- end -}}
  {{- end }}
  <updated>{{ now.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>
  {{ with site.Author.name -}}
    <author>
      <name>{{ . }}</name>
      {{ with site.Author.email }}
        <email>{{ . }}</email>
      {{ end -}}
    </author>
  {{- end }}
  {{ with site.Params.id }}
    <id>{{ . | plainify }}</id>
  {{ else }}
    <id>{{ .Permalink }}</id>
  {{ end }}
  {{- $limit := (cond (le site.Config.Services.RSS.Limit 0) 65536 site.Config.Services.RSS.Limit) }}
  {{- $pages := .Pages -}}
  {{/* Remove the pages that have the disable_feed parameter set to true. */}}
  {{- $pages = where $pages ".Params.disable_feed" "!=" true -}}
  {{/* Remove the pages that have the unlisted parameter set to true. */}}
  {{- $pages = where $pages ".Params.unlisted" "!=" true -}}
  {{- range first $limit $pages }}
    {{ $page := . }}
    <entry>
      {{ printf `<title type="html"><![CDATA[%s]]></title>` .Title | safeHTML }}
      <link href="{{ .Permalink }}" rel="alternate" type="text/html" />
      {{- range first 5 (site.RegularPages.Related .) }}
        <link
          href="{{ .Permalink }}"
          rel="related"
          type="text/html"
          title="{{ .Title }}" />
      {{- end }}
      {{ with .Params.id }}
        <id>{{ . | plainify }}</id>
      {{ else }}
        <id>{{ .Permalink }}</id>
      {{ end }}
      {{ with .Params.author -}}
        {{- range . -}}
          <!-- Assuming the author front-matter to be a list -->
          <author>
            <name>{{ . }}</name>
          </author>
        {{- end -}}
      {{- end }}
      <published>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</published>
      <updated>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>
      {{ $description1 := .Description | default "" }}
      {{ $description := (cond (eq "" $description1) "" (printf "<blockquote>%s</blockquote>" ($description1 | markdownify))) }}
      {{ printf `<content type="html"><![CDATA[%s%s]]></content>` $description .Content | safeHTML }}
      {{ with site.Taxonomies }}
        {{ range $taxo,$_ := . }}
          <!-- Defaults taxos: "tags", "categories" -->
          {{ with $page.Param $taxo }}
            {{ $taxo_list := . }}
            <!-- $taxo_list will be the tags/categories list -->
            {{ with site.GetPage (printf "/%s" $taxo) }}
              {{ $taxonomy_page := . }}
              {{ range $taxo_list }}
                <!-- Below, assuming pretty URLs -->
                <category
                  scheme="{{ printf "%s%s" $taxonomy_page.Permalink (. | urlize) }}"
                  term="{{ (. | urlize) }}"
                  label="{{ . }}" />
              {{ end }}
            {{ end }}
          {{ end }}
        {{ end }}
      {{ end }}
    </entry>
  {{ end }}
</feed>

Generated Feeds