Excluding a category from the blog homepage

How do I exclude a category from being visible on the blog homepage? It should still appear in MB’s timeline and my archives.

I tried some code from a Hugo Support forum but didn’t work. Perhaps because I’ve customized the homepage to list posts chronologically within a day. See code in the attached screenshot. Assuming it should be in /list.html

I’m using @amit’s Musings theme.

1 Like

Hmmm. I read it and think I could just filter out the posts if it has the category. Not sure if that’s the best way, though. It’s especially difficult, given I do not use the theme anymore. But I will test it out sometime and try to figure out a way.

Thanks, Amit. Also, I included the template as an example. I was looking for a more generic code for Hugo to exclude a category on a page or, on the flipside, to display posts from only one category on a separate page.

@pratik In that case, this should help you. Can you try it?

{{ range where .Site.RegularPages "Params.categories" "intersect" (slice "Motherboards") }}

This is to display posts from only one category (Motherboards) on the homepage and not to exclude it, right?

For excluding posts from a certain category on the homepage, I found this. But not sure if I need to add this to layouts/index.html or layouts/_default/list.html. I tried both but got errors. I may have inserted them in the wrong place.

Here’s the code for the index file:

It would be in layouts/index.html. Can you share the code that you tried which errored out?

It was linked in the earlier post - Exclude a category from list.html - support - HUGO

I put the code after {{ if eq .Type "post" }}

I would filter further up, prior to the grouping. Either when setting $posts or right after-- probably by adding and to your existing where.

1 Like

Agreed with @jsonbecker. You should filter even before you begin to range on it.

So just add {{ if not (in .Params.categories "Blog") }} just after the <h3> line or after the <main class...>?

BTW what’s the syntax if I want to add an 'and to the where statement?

@amit Tried it at both places but threw up a parsing error for both.

I have managed to get it working, but the other way around. Basically, display posts with specific categories, not exclude them. It should be possible but just can’t think of a simple way.

I did this alteration on the default homepage post listing. My use case is I copy all my Letterboxd reviews to my Micro.blog but I don’t want them to show up on the homepage (because I watch a lot of movies and don’t want them to clog up the view).

It seems to work at first, but it actually only filtered out the first four posts. Once it hits a post that passes the “if not” test, the subsequent Letterboxd reviews show on the page. :sweat:

<ul id="post-list">

{{ if or .IsHome .Site.Params.paginate_categories }}
	{{ $paginator := .Paginate (where .Site.Pages.ByDate.Reverse "Type" "post") }}
	{{ $list := $paginator.Pages }}
	{{ range $list  }}
		{{ if not (in .Params.categories "Letterboxd") }}
		{{ partial "post-item.html" . }}
		{{ end }}
	{{ end }}
{{ else }}
	{{ $list := where .Site.Pages.ByDate.Reverse "Type" "post" }}
	{{ range $list  }}
		{{ if not (in .Params.categories "Letterboxd") }}
		{{ partial "post-item.html" . }}
		{{ end }}
	{{ end }}
{{ end }}

</ul>

{{ $paginator := .Paginate (where (where .Site.Pages.ByDate.Reverse "Type" "post") ".Params.categories" ne "Letterboxd") }}

You do not want to filter after paginating or after doing a range. You want to filter out these posts at the first point you’re developing what set of pages are valid for your collection.

In @pratik’s case, something like this

{{ $posts := where (where .site.RegularPages "Type" "post") ".Params.categories" eq "Motherboards" }}

Would work. Or something quite similar.

I believe this doesn’t work as the categories param is a list. I got this working. Doing it as a negative is trickier.

{{ $posts := where site.RegularPages "Type" "post" }}
{{ $posts = where $posts ".Params.categories" "intersect" (slice "dev" "sample") }}

cc @pratik

Thanks! This works for now. I tried all sorts of different permutations for the previous suggestion and it just doesn’t seem to want to work. It’s a bit of a pain having to jump in and update every time I add a category, and doesn’t work well with putting posts in multiple categories. Would love to see a plug-in that simplifies this. :slight_smile:

Hugo’s symdiff function returns the symmetric difference between two collections. That’s just a fancy way to say: “give me the things that are in either of these collections but not in both”.

So, if you have all posts in one collection, $posts, and posts from the category you want to exclude in another collection, $hidden_posts, you can get all posts sans excluded posts with $posts | symdiff $hidden_posts. Something like this:

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

In the example above, $posts will contain all posts except posts in the category Hidden .

1 Like

Nice! Thank you, @sod. Learnt a new thing. This should do what @pratik needs.

Replace line 2 in layouts/index.html with this code block that Sven shared. Place categories that you want to exclude in second line next to slice (for example, dev, tech in the example),

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

I have tested this, works as expected.

1 Like

This is fantastic. Thanks, @sod, @amit and @jsonbecker. This is why I love Micro.blog. You get to learn new things every day.

1 Like