Customizing Hugo RSS Feeds

Yesterday I griped about the way Hugo generates RSS feeds for every section and taxonomy, and how it names them all index.xml. Then, not long after I posted my complaints, I found all the answers I’d been seeking.

First, the default RSS handling in Hugo is weird. Anyone who thinks it’s how RSS should work on a website is … well, let’s just use the word wrong and smile in a friendly manner while we do. But it’s wrong.

The good news is, both of my desired changes, having one RSS feed for my blog posts only and having that feed named feed.xml, are quite simple to achieve. All that’s needed are some minor additions to the site config file and an RSS template.

The list of steps to perform are as follows:

  • Configure the site to have one single RSS feed in the site’s root directory.
  • Configure your site to name this RSS file “feed.xml” instead of “index.xml”.
  • Edit your site’s RSS template so only blog posts show up in your RSS feed rather than every new page regardless of type.
  • Edit your site’s RSS template to show full blog posts per feed item instead of blog post summaries.

It sounds like a lot, but it’s really not that involved.

To configure your site so that there is one single RSS feed in the root directory, add the following section to your config.toml (or whatever format your config file is):

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

This tells it to give your “home” section both RSS and HTML elements when compiled, but to only compile the HTML output for different site sections and taxonomies.

You’ll also want to edit your RSS template if you only want posts in your feed, which I’ll show you in a minute.

First, let’s tackle the feed naming issue. I want feed.xml as my feed name, which is accomplished by adding yet another section to the config file:

[outputFormats]
[outputFormats.RSS]
  mediatype = "application/RSS"
  baseName = "feed"

At this point, we’ve gotten rid of much of the default RSS behavior of Hugo that irritates me so much. But we still need to make some changes to the RSS template.

Hugo’s default RSS template is detailed on their RSS Templates overview. Copy this template and paste it into a new file called rss.xml in the layouts directory (layouts/rss.xml).

By default, Hugo’s RSS template is set to display all types of content. If you want to limit it to blog entries only, you have to change the following line in rss.xml

{{ range .Pages }}

to

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

Your blog post section may or may not be called “posts”. It’s the directory under content/ where you place your blog post .md files.

posts directory

If your blog post directory is named something else, substitute that for “posts” in the example above.

You may wish to make one more tweak to your RSS template if you want full posts to show up for people subscribed to the feed rather than post summaries (which require clicking a link to finish reading the full post).

Find the following line in rss.xml

<description>{{ .Summary | html }}</description>

and replace it with the following by changing .Summary to .Content

<description>{{ .Content | html }}</description>

Again, only do this if you want full blog posts articles in your feed instead of summaries which require your feed subscribers to click and visit the blog post page on your site to finish reading your article.

And that’s pretty much it for taming the wildness that is the default Hugo RSS setup. Not spewing 1000 RSS feeds all over the place for no reason has its appeal.

Unfortunately, while writing this, I started going down the rabbit hole of code listings with line numbers and highlighting. That’ll be a topic for another day, because now I need to figure out how to do that.