Enable RSS for one specific section in Hugo

 Sun, 28 Apr 2024 09:34 UTC

Enable RSS for one specific section in Hugo
Image: CC BY 4.0 by cybrkyd


Hugo’s configuration options allow for turning RSS output on and off for “home”, “section”, “taxonomy” and “term”. An example config.toml can be setup as follows, where RSS output is enabled for “home” only:

[outputs]
  home = ["html", "rss"]
  section = ["html"]
  taxonomy = ["html"]
  term = ["html"]

This outputs RSS for the entire site where a list-type page exists; i.e. the home page which is the list of all the blog posts.

I would like to have RSS enabled for “section” but not all sections. My folder structure is like this:

content
├── notes
│   ├── note-01.md
│   ├── note-02.md
│   └── ...
├── page
│   ├── about.md
│   └── contact.md
├── post
│   ├── post-01.md
│   ├── post-02.md
│   └── ...
└── search
    └── _index.md

I recently added the “notes” section and would like an RSS output from there but it needs to be separate from my main RSS. Unfortunately, turning on RSS for “section” will generate RSS for “page”, “post” and “search” as well as “notes”, often with repeating content in the various outputs.

Enabling RSS for one sub-section only in Hugo

My Requirements are:

  • Two separate RSS outputs: one for “post” and the other for “notes”.
  • The two RSS streams should not contain any crossover of items.

My Hugo theme did not contain a rss.xml file in layouts/_default and therefore used the RSS configuration from the core. Further, my version is…

$ hugo version
hugo v0.92.2+extended linux/amd64 BuildDate=2023-01-31T11:11:57Z VendorInfo=ubuntu:0.92.2-1ubuntu0.1

…so I couldn’t simply copy > paste the rss.xml from the GitHub repo.1 I did try but it all went wrong, so after a bit of light reading,2 I decided that it was best to DIY this one.

Create an _index.md

In the section “notes”, create a file _index.md and add the following to it:

+++
outputs = ["rss", "html"]
+++

This instructs Hugo to output both html and RSS for that specific section.

Build the RSS generator template

In layouts/_default, create a new file rss.xml and add the following to it. This file will now be used to specify the basic RSS template.

{{ if ne .Section "notes" }}{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ .Site.Title }}</title>
    <link>{{ .Permalink }}</link>
    <description>Posts from {{ .Site.Title }}</description>
    <generator>Cybrkyd's RSS generator for Hugo</generator>
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>
    <atom:link href="{{ .Permalink }}" rel="self" type="application/rss+xml"/>
    {{ range where .Site.RegularPages "Section" "post" }}
        <item>
        <title>{{ .Title }}</title>
        <link>{{ .Permalink }}</link>
        <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
        <guid>{{ .Permalink }}</guid>
        <description>{{ .Summary | html }}</description>
        </item>
        {{ end }}
  </channel>
</rss>
{{ else }}{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ .Site.Title }} - Notes</title>
    <link>{{ .Permalink }}</link>
    <description>Notes from {{ .Site.Title }}</description>
    <generator>Cybrkyd's RSS generator for Hugo</generator>
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>
    <atom:link href="{{ .Permalink }}" rel="self" type="application/rss+xml"/>
    {{ range where .Site.RegularPages "Section" "notes" }}
        <item>
        <title>{{ .Title }}</title>
        <link>{{ .Permalink }}</link>
        <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
        <guid>{{ .Permalink }}</guid>
        <description>{{ .Content | html }}</description>
        </item>
        {{ end }}
  </channel>
</rss>
{{ end }}

Because I wish to output separate RSS feeds for “post” and “notes”, the template is set to differentiate between the two.

The first output is for “post”:

{{ range where .Site.RegularPages "Section" "post" }}

and the second output will create the feed for the “notes” section:

{{ range where .Site.RegularPages "Section" "notes" }}

The {{ if ne .Section "notes" }} makes sure that no pages from “notes” are added to the RSS for “post”. We therefore must have another complete RSS generation in the same file which is devoted to outputting the RSS for “notes”. I did try various if/else set-ups of the rss.xml in an effort to shorten it and but I failed miserably, so I left it as-is, above.

In conclusion, I settled on this as it delivered the objective: (1) continue to output the main posts RSS and (2) enable RSS for one specific sub-section of Hugo.


  1. Hugo’s default rss.xml: Default rss.xml ↩︎

  2. Hugo’s RSS templates: RSS templates ↩︎