Listing Categories by Blog

Hey all,
I’ve got a website where I essentially have two different blog pages that occasionally share similar content and therefore need a post/category to appear on both pages. Is there any easy way to do this?

I am able to correctly hide posts from one page or the other by using
{% if post.categories contains ‘Unwanted Category’ %}
do nothing
{% else %}
display posts

However at the top of the blog pages I list the categories. This is where I am having a hard time of only listing certain categories on each blog page.

you don’t need to do it as a category - unwantedCategory could be a front matter variable and you could do much the same thing I think.

You have two groups if you split by display page. Group A and Group B, and each post could be in one or both.

Categories are hierarchical, so setting something to be in category A and B actially makes the URL have A first and then B.

You can use Jekyll post labels like

---
tags: group_a group_b
---
site.tags.group_a  # all matching posts 

There is no hierarchy or order and it does not affect the output URL.

And you can reference as post.tags and check if a post’s tags including a certain tag

Or more easily get all posts within a certain tag.

The other comment suggests an approach where you make up a value and use that

---
group_a: true
group_b: false
---

I’m still not quite sure how to implement this in my case. I understand how to only show posts with a certain tag, but how do I only show categories belonging to those certain tags? This is the script I am using currently, which does not work.

<h2>Topics by Post Count</h2>
	<ul>
		{% assign categories_list = site.categories %}
		{% if categories_list.first[0] == null %}
		{% for category in categories_list %}
		<!-- <a href="/Topics/#{{ category | url_escape | prepend site_url }}">{{ category | camelcase }} ({{ site.tags[category].size }})</a> | -->
		{% endfor %}
		{% else %}
		{% for category in categories_list != 'unwantedcategory' %}
		<a href="/topics/#{{ category[0] | url_escape | site_url }}">{{ category[0] | camelcase }} ({{ category[1].size }})</a> |
		{% endfor %}
		{% endif %}
		{% assign categories_list = nil %}
	</ul>

Have you tried using Jekyll’s where and where_exp filters? Those should give you more options in combination with an assign.

I have not used the where and where_exp filters because I would have to list out each category to filter. So every time a new category is added I would have to remember to go back into the code and add it into the where expression.

Is there not a way to essentially have 2 separate blogs within the same site? I think this would be the best approach, and I’ve tried it, but the site.categories variable still picks up all the categories across the site, whereas I need it to only list the categories pertaining to one blog or the other.

Yeah, you’re working against how core Jekyll works. It’s not designed to do 2 blogs in one site.
site.categories does what the tin says… it’s your site’s categories.

Technically, you can create two blogs on one site, and there are many examples of how to do that. I created a video series on Jekyll and came up with one of many approaches in the video link at the bottom of this post.

I think what you really want is a URL that looks like this:

https://www.mysite.com/categories?category=cars

The result would be a page that displays the blog items you have that talk about the category of cars. Whenever there is a new category, the link changes to that name, and you are good to go. Sounds good, right? Unfortunately, In a Jekyll/static site world, you cannot programmatically figure something out at runtime, so you have to create individual files to handle the routing, but it is pretty easy to do that.

You can create a folder called categories and then create a file per each (yes, you still need to do the heavy lifting, but the page would be easy to create).

Create a page in the categories folder and call it cars.md with whatever front matter you want, like:

---
layout: default
category: cars
---

Now, in the default layout (or whatever layout you create), you would have code somewhere in there that looks like this:

{%- assign posts = site.posts | where_exp: 'post', 'post.category == category -%}
{%- for post in posts -%}
  your html and code here...
{%- endfor -%}

If you create a new category and call it trucks, add another file in the category folder, call it trucks.md, and update the front YAML front matter with category: trucks.

Jekyll does have a capability referred to as collections, where you can create a grouping of any data, like a second blog, for example. Here are the official docs:

I think the following thread covers a lot of your questions in a slightly different context, but still what I think you are asking for:

Here is a video I created a while back with one way you can have multiple blogs on a single site. I do not think this is what you want, but it could be helpful! It is part of a training series, so it assumes you have a Jekyll site set up locally with the default minima theme.

I think I am close to getting what I want. I am using categories like normal, but have added two different tags to each posts’ front matter.I am trying to create a list of categories belonging to posts in each tag, tag “A,” or tag “B.”

							<h2>Topics by Post Count</h2>
							<ul>
								{% assign categories_list = site.categories %}
								{% if categories_list.first[0] == null %}
								{% for category in categories_list %}
								<!-- <a href="/Topics/#{{ category | url_escape | prepend site_url }}">{{ category | camelcase }} ({{ site.tags[category].size }})</a> | -->
								{% endfor %}
								{% else %}
								{% for post in site.tag.['B'] %}
								<a href="/topics/#{{ category[0] | url_escape | site_url }}">{{ category[0] | camelcase }} ({{ category[1].size }})</a> |
								{% endfor %}
								{% endif %}
								{% assign categories_list = nil %}
							</ul>

However, the code above doesn’t seem to be doing anything. Any guesses as to why?

This is bad code. tags not tag

And either

site.tags.B

Or

site.tags['B']

Not both.

Try simpler code first like without null check and just printing the category name and then if that works you can add more stuff.

The way you iterate over categories is not correct.

It is a hash which gets unpacked as a pair of category name and posts in the category

See c[0] and c[1] and related code in this guide

Even following the linked guide I am unable to get a list of tags belonging to Blog B. Does this method only work for categories maybe?

								{% for c in site.tags['Blog B'] %}
									{{ c[0] }}
								{% endfor %}

Liquid Exception: 0 is not a symbol nor a string

With this code, I am trying to get all categories associated with tag “Blog B”

Or if there truly isn’t a way to do this, could I just find a way to list only the categories belonging to “Blog B” manually?

Try

{{ c | inspect }}

So you can see what c contains.

Did you definitely use 0 as a number and not O as a letter?

{{ c[0] }} {{ c[1] }}

It appears to contain the HTML of the current page.

I confirmed the use of 0 as a number.

I’d say then reduce your scenario to be more generic and then customize after.

So firstly take out spaces of tags and use hyphen instead.

tags: blog-b blog-c

If you used spaces…

tags: blog b blog c

That becomes blog, b, blog, c, as 4 items

Unless you are explicit

tags: ["blog b", "blog c"]

Secondly you can try a more generic piece of code which works elsewhere.

{% assign tags = site.tags | sort %}

{% for tag in tags %}
<h3>#{{ tag[0] }}</h3>

{% for post in tag[1] %}
- [{{ post.title }}]({{ post.url | relative_url }})
{% endfor %}
{% endfor %}

Which is like doing this for each tag.

assign tag = site.tags.abc
tag[0]
tag[1]

And your c value (or my tag value) should contain more than the HTML that you said.

It should be something like

[
  "Blog B",
  [<post 1>, <post 5>, ... ]
]

Is there not a way to essentially have 2 separate blogs within the same site?

The simplest way is to use the first category in each post as blog name and alter the global permalink to output the pages taking categories into account. You may arrange the different content in two different _posts subfolders, one for each blog, just to make everything well organized.

You might also create collections of authors as the example in this page show: GitHub - cameronmcefee/jekyll-authors: Example of using authors in Jekyll posts

At this point to render different categories for different blogs, you can create two different layouts or consider within your single layout the nature of your post reading the first category or the author specified in the front matter. For every blog create a list of categories to embed, this list can be a _data file for each blog, or just a variable embedded in the layout (not recommended though), the layout will choose which list to read from.