How to go from nothing to a custom RSS feed

I’m trying to figure out how to exclude one category from my main RSS feed. I would like to exclude my reading list so that I can use the main feed to cross post in a less noisy way.

I think I need to:

Create a reading list category (Reading List)
Set up a filter to automatically put posts containing :books: into that category
Create a new blank theme (which automatically clones my current theme)
Modify the layouts/_default/rss.xml template

According to @sod’s helpful post about symdiff it seems like I should be able to exclude that one category with something like:

{{ $posts := where site.Pages "Type" "post" }}
{{ $hidden_posts := where $posts "Params.categories" "intersect" (slice "Reading List") }}
{{ $posts = $posts | symdiff $hidden_posts }}

But the existing collection seems to be being fetched with {{ range .Pages }}.

Is it as simple as updating that with:

-     {{ range .Pages }}
+     {{ $posts := where range.Pages "Type" "post" }}
+     {{ $hidden_posts := where $posts "Params.categories" "intersect" (slice "Reading List") }}
+     {{ $posts | symdiff $hidden_posts }}

Thanks in advance for any advice!


Update: I tried the above on my test blog ( and it didn’t seem to work.

First I set up the category and filter and checked to make sure the categorisation was working (Reading List). Then I tried the above code along with a few variations on it:

  • slicing on “reading-list” instead of “Reading List”
  • adding range to the start of the last line: {{ range $posts | symdiff $hidden_posts }}
  • splitting the last line into two lines:
    {{ $posts = $posts | symdiff $hidden_posts }}
    {{ range $posts }}

That all looks about right. I’m far from a computer, but this is a great example of a question that’s really about Hugo and almost certainly you’ll get more/better help searching the Hugo forums or posting there.

I was hoping for a simple, specific answer without having to dive into Hugo but no matter :wink:

There’s still lots I don’t know and it’s still not working but for anyone following in my meandering footsteps I think I identified the following problems:

  1. I shouldn’t have included the first range:
- {{ $posts := where range.Pages "Type" "post" }}
+ {{ $posts := where .Pages "Type" "post" }}
  1. I don’t know but I suspect the $posts = $posts | ... syntax contains a typo… All the other examples I’ve seen (including the previous two lines) use := instead of =.

  2. I’m not sure whether Hugo likes $variables being reused but passing the symdiff straight to range didn’t seem to help either.

Even fixing those things didn’t help.

This Hugo forum answer lead me to try complement instead but that didn’t seem to help:

    {{ $posts := where .Pages "Type" "post" }}
    {{ $hidden_posts := where $posts "Params.categories" "intersect" (slice "Reading List") }}
    {{ range ( $posts | complement $hidden_posts ) }}

(I later checked to see if complement and symdiff are supported in Hugo 0.54… according to the release docs they were both added in 0.51 :man_shrugging:)

Then I tried to check if $hidden_posts was being set correctly by passing it to the range but I still get all the posts :man_facepalming::

    {{ $posts := where .Pages "Type" "post" }}
    {{ $hidden_posts := where $posts "Params.categories" "intersect" (slice "Reading List") }}
    {{ range $hidden_posts }}

I found another Hugo forum post that combines wheres but I couldn’t get that working either*:

    {{ range (where (where .Pages "Type" "post") ".Params.category" "!=" "Reading List" ) }}

*Question Does the RSS feed get regenerated when I make changes to layouts/_default/rss.xml or does it only impact newly added items? Before this last attempt I was adding two new test items each time but it was making the feedback loop extremely slow so I stopped.

What an exemplary thread start, I see that you’ve done your research and you’re definitely on the right track. But the template you’ll want to modify is probably layouts/index.xml. layouts/_default/rss.xml is applied to category feeds (like /categories/family/feed.xml) but not the main feed (/feed.xml).

Before going down this road, have you considered adding the category feeds you want to be included on the timeline to the Edit Sources & Cross-posting page instead? And remove the main feed, to avoid duplicate posts.

That way, you get control of cross-posting per category and don’t have to fiddle around with custom templates.

Hmmm… my first instinct was to say “but what if I create new categories in the future?! I’ll have to remember to add them to the list of sources”.

But you’re right @sod, that is a better option. I don’t often add or change categories and if I do it’s not the end of the world if I forget to specifically include one for a day or 365.

I plan (but don’t promise) to write up a more complete collection of my learnings to round out this thread in case anyone else follows me down this rabbit hole but I would like to test your suggested solution first. New questions it brings up:

  1. Is it possible to edit the Sources for my test blog so I can test this out quietly? (Not that I have any subscribers but it’s good practice not to mess with production if I’m not sure what’s going to happen)
  2. Is there a feed containing just posts without a category or would I have to categorise every post I want showing up? (Not a deal breaker, just trying to understand)
  3. If there’s not a feed for uncategorised posts, is there a filter that could automatically add an “Uncategorised” category if no other manual or filter categories apply to a post? (Again, not essential, just evaluating options)
  4. Will adjusting this change which posts get displayed in all the places. I’m not sure what all the places are but I’m thinking:
    • Timeline in
    • Main page of my blog
    • Main RSS feed
    • Cross-posting destinations*

*Note: So I’ve just broken my “don’t mess with production” rule and temporarily added one category form test as a Source. It seems like if I go down this path I’ll have a bunch of Sources listed (one per category) and I’ll be able to (or have to if I’m being pessimistic) individually manage cross posting for each category. Is that right?

I think there are issues if a post is in one or more category with this method so I wouldn’t advise it. The correct thing is to use the methods you were using earlier with intersect as referenced in the original thread but on the correct feed— your index feed— and not the category feed.

The easiest way to test this all out is to build a very small Hugo site locally and manually add categories to the standard example site content and mess with it until you get the result you want. It’ll be way faster.

1 Like

I’m not sure it’s the better option. :smile: Definitely not in all cases. But it’s an option that needs less tinkering with custom themes. On to your questions…

  1. Yes, you should be able to add your test blog’s feeds to the Edit Sources & Cross-posting page. The test posts will show up on your public timeline, though. There’s not really a way around that, other than creating a new free account only for testing (like matt17r_test).
  2. Yes, you would have to categorize every post.
  3. No, unfortunately not.
  4. Changes made on the Edit Sources & Cross-posting page only affect your timeline and cross-posting. Your blog will be unaffected. And yes, you have to manage cross-posting for every category/feed you add there.

So yes, this approach has its downsides with the upside being that you’re just tinkering with vanilla settings instead of having to make changes in a custom theme.

As @jsonbecker points out, this solution is not for you if your posts can belong to more than one category. That would result in duplicate posts on your timeline.

1 Like

Hey @matt17r not sure if you’ve solved this but I was trying to do something similar. My not exactly elegant solution is as follows:

  1. Created a category mbtimeline.
  2. Created filter that applies mbtimeline to Post Length = Short.
  3. Created filter that applies mbtimeline to Post Length = Long.
  4. Ran filter to add mbtimeline to all my past posts (I don’t have a lot at the moment).
  5. Deleted main feed from Edit Sources & Cross-posting page.
  6. Replaced with categories/mbtimeline/feed.xml.
  7. Delete filters from 2 and 3 as I don’t want all future posts to have mbtimeline auto-assigned.

So in theory, anything I post in future will have an opt-in via mbtimeline category before hitting publish. I have no other categories at the moment so it will be a consideration I’ll have to remember if/when I make more use of this function.

Thanks to @sod and his reply in this thread – where I got the idea from!