Displaying full content in RSS with Hugo

matthias on 2017/12/06

After deployment, the default RSS feed of Hugo had several issues for me that I now adjusted: full article content in the feed, only blog posts, limit to last 15 posts.

Motivation

In general, I’d like the RSS feed of my site to be at least as useful as it previously was. As a reader, I don’t like it when authors force you to come to their website by truncating the article content in the RSS feed. For that reason, I don’t want to do it either. The other changes are cosmetic in nature. There should be no reason to have single pages, like “About”, show up in the feed. The limitation on posts is not strictly necessary; it makes sense because the resulting xml can grow large when the full content is included.

How?

To get the RSS feed I wanted, I started from the embedded RSS template. In other words, I made the implicit default of Hugo explicit. I reproduce that template here for completeness.

<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>{{ .Summary | html }}</description>
    </item>
    {{ end }}
  </channel>
</rss>

I added that template under “themes//layouts/_default” and applied the following changes.

o C6HfH matt@hp840:~/dvl/www_matthiaskauer_com/themes/xmin-bootstrap/layouts (master)*$ git diff 668e4d1 -- _default/rss.xml
diff --git a/themes/xmin-bootstrap/layouts/_default/rss.xml b/themes/xmin-bootstrap/layouts/_default/rss.xml
index 8fa3969..aac2451 100644
--- a/themes/xmin-bootstrap/layouts/_default/rss.xml
+++ b/themes/xmin-bootstrap/layouts/_default/rss.xml
@@ -12,14 +12,14 @@
     {{ with .OutputFormats.Get "RSS" }}
         {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
     {{ end }}
-    {{ range .Data.Pages }}
+    {{ range first 15 (where .Data.Pages "Section" "!=" "") }}
     <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>{{ .Summary | html }}</description>
+      <description>{{ with .Description }}<p class="lead">{{ . }}</p>{{ end }}{{ .Content | html }}</description>
     </item>
     {{ end }}
   </channel>

This worked for me but a few words are still in order.

  • Obviously, it’d be better to have a parameter for the hard-coded 15 posts I am currently showing.
  • {{ with .Description }}<p class="lead">{{ . }}</p> shows the description of your post. I use “.Description” in a special way on my site. You may hence want to remove that.

Testing

I did not want to test in production but my main RSS reader is web-based and cannot access my local test server. For this reason, I tested with Newsbeuter, a command-line RSS reader, and QuiteRSS a Qt-based RSS reader with GUI. They can be installed with apt install quiterss newsbeuter on Ubuntu & Co.

The new feed seems to work in both test readers. I will only really know whether it works after I deploy though. If you notice any issues, please let me know!