Limiting The Generation Of RSS Feeds In Hugo

I’m new to Hugo and while creating this website I noticed that RSS feeds were being generated for all my content sections. For security and privacy reason I only want an RSS feed created for my blog posts, and not for the other content sections.

To achieve this, four things need to happen.

  1. The site configuration file needs to edited so that only content sections output RSS.
  2. Front matter needs to specified in the _index.md file of each content section that is not to have an RSS feed.
  3. A custom layout needs to be created for the RSS feed that limits generation based upon content sections.
  4. The site configuration file needs to be edited again to use the newly defined custom layout.

The simplified site Hugo directory structure for this post will be:

dereckcurry.com
    content
        posts
            hello-world.md
            hugo-section-rss-feeds.md
        images
            _index.md
            avatar.jpg
    layouts
        _default
            rss.xml
    config.toml

Step 1: Limit RSS Feed Generation To Only Content Sections

The first step is to limit the generation of RSS to only sections via the outputs settings in the site config.toml configuration file. The configuration file snippet below turns off RSS for all output settings except for sections.

[outputs]
    page = ["HTML"]
    home = ["HTML"]
    section = ["HTML","RSS"]
    taxonomyTerm = ["HTML"]
    taxonomy = ["HTML"]

The config file changes indicate that RSS should only be generated for sections. All other Hugo output categories will generate only HTML. If you need to use some custom output types, you’ll need to include those in above configuration.

Note: I was unable to find any documentation describing how to explicitly stop the RSS generation for categories and tags used on the site. In my case I was ok with the RSS generation for those, but If you want to keep RSS from generating then you can explicitly deny them in a custom RSS layout file. See further down in this post for information about creating a custom RSS layout file.

Step 2: Disable RSS Feed Generation In Unwanted Content Sections

At this point, all content sections will still generate RSS, including the images section in our example above. To keep a content section from generating an RSS feed, an _index.md file needs to created (if it doesn’t already exist) in the section and the following directive needs to be included in the front matter of the file. In this case, I’m using YAML for the front matter configuration.

---
outputs:
- html
---

The above front matter explicitly removes RSS an output format for the content section. This should override the config.toml settings and keep the RSS feed from being generated. In addition, the RSS link will not be included in the HTML head for the section so long as your Hugo theme checks for the existence of the .RSSLink variable (or if it does a with .OutputFormats.Get “RSS” check) before generating the content. If your theme doesn’t check for .RSSLink or with .OutputFormats.Get “RSS”, then you may need to create a custom layout replacing the theme’s layout with one that performs the check. An example of the with .OutputFormats.Get “RSS” check is below, but the location of the RSS check will be dependent on the layout organization of the theme you have selected for your site.

<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
  <head>
    ... Head theme stuff ...

    {{ with .OutputFormats.Get "RSS" }}
      <link href="{{ .RelPermalink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" />
      <link href="{{ .RelPermalink }}" rel="feed" type="application/rss+xml" title="{{ .Site.Title }}" />
    {{ end }}

    ... More Head theme stuff ...
  </head>
  <body>
    ... Body theme stuff ...
  </body>
</html>

According to warnings generated with Hugo version 0.55, .RSSLink has been deprecated and with .OutputFormats.Get “RSS” should be used for the RSS check, and .RelPermalink should be used instead of .RSSLink in the href portion of the <link /> tag.

Step 3: Create A Custom Layout RSS file

Finally, just to be safe, I created a custom layout for the RSS file that limits the generation of the RSS file to the posts section, but will also allow for the generation of RSS for categories and tags. The custom layout is stored in the layouts/_default/ directory and named rss.xml. In the below code example, the RSS limiting is handled via the first line of the code.

This template is based upon Hugo’s default RSS xml template.

{{ if or (eq .Section "posts") (eq .Section "categories") (eq .Section "tags") }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ if eq  .Title  .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
    <link>{{ .Permalink }}</link>
    <description>Recent content {{ if ne  .Title  .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
    <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
    <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
    <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
    <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
    <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
    {{ with .OutputFormats.Get "RSS" }}
	    {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
    {{ end }}
    {{ range .Data.Pages }}
    <item>
      <title>{{ .Title }}</title>
      <link>{{ .Permalink }}</link>
      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
      {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
      <guid>{{ .Permalink }}</guid>
      <description>{{ .Content | html }}</description>
    </item>
    {{ end }}
  </channel>
</rss>
{{ end }}

Note: The above code will still generate RSS for all other sections if they are not explicitly denied in the front matter of the section’s _index.md file (see above), but the generated RSS file will be empty.

Also Note: I changed the default Hugo RSS template value to to use .Content instead of .Summary. I’m not monetizing my blog with advertising, so actual page hits aren’t necessary in my case and any RSS feed readers are fine to present the full blog post.

Step 4: Instruct The Site To Use The New Custom RSS Feed Layout

In order to use this new RSS layout, you’ll need to modify the config.toml file once again. This time the outputsFormats.RSS will need to have a modified baseName value that reflects the new template name. In this case, rss is used since the default layout file name is rss.xml.

[outputFormats]
    [outputFormats.RSS]
        baseName = "rss"

For completeness, here are all the RSS changes needed for the config.toml in one place.

[outputFormats]
    [outputFormats.RSS]
        baseName = "rss"

[outputs]
    page = ["HTML"]
    home = ["HTML"]
    section = ["HTML","RSS"]
    taxonomyTerm = ["HTML"]
    taxonomy = ["HTML"]

Bonus: Additional RSS Settings

While, we are on the subject of the site’s config.toml file, I also made the following change to limit the RSS feed to the past 20 posts. I’m not certain how large this blog will grow to, but figured that 20 should be an appropriate number of posts to show a feed reader.

rssLimit = 20

I also set the language and copyright notice in the config.toml file.

languageCode = "en-us"
copyright = "&#169; Dereck Curry. All rights reserved."

Finally, I set the author value in config.toml.

[author]
    name = "Dereck Curry"

Here ere are all the RSS changes for the config.toml in one place.

rssLimit = 20

languageCode = "en-us"
copyright = "&#169; Dereck Curry. All rights reserved."

[author]
    name = "Dereck Curry"

[outputFormats]
    [outputFormats.RSS]
        baseName = "rss"

[outputs]
    page = ["HTML"]
    home = ["HTML"]
    section = ["HTML","RSS"]
    taxonomyTerm = ["HTML"]
    taxonomy = ["HTML"]

Caveats

As stated earlier, I was unable to find any documentation describing how to explicitly stop the RSS generation for categories and tags used on the site. In my case I was ok with the RSS generation for those, but If you want to keep RSS from generating then you can explicitly deny them in a custom RSS layout file.

It doesn’t appear that static directories generate RSS feeds, so please don’t go creating content sections if you don’t need to. In my example, the content/images/ directory only had the single avatar.jpg image and it really wasn’t necessary to make a content section for it. Placing the image in the static/images/ directory would have been fine. But the use of an images directory in the content section seemed like a reasonable choice for this post as there is likely to be a need to use such a content section at some point in the future.

When running the internal Hugo server, I was still able to get to the RSS file for all the content sections by directly entering the URL for the RSS feed in my browser. This seems like it might be a bug to me, but I really didn’t investigate the Hugo GitHub account see if it had been reported or not. But the good news is that when generating the static site, the RSS file was properly excluded. And since I selected Hugo for static site generation, I’m ok with this behavior.

Conclusion

For more information about Hugo output formats, site configurations, and section configurations, please see the Hugo documentation on the subject. The Hugo documentation also includes a significant section on RSS templates and configuration settings that is worth a read.

I hope you find the above information useful.

Dereck

comments powered by Disqus