Collections appear to be an ill-documented feature of Jekyll, and the documentation seems to make the most sense if you’re already familiar with collections.
The old way of building out categorization in Jekyll was to set the categories
front-end matter in the following kind of manner:
/_posts/2000-01-01-some-post.md
---
title: Some Post
categories: ["Some", "Category"]
---
You could further elaborate on this tagging my changing either the permalink
in the posts frontend matter, or by adding the following configuration to your _config.yml
file, with zero tabation:
/_config.yml
permalink: /:categories/:title
With collections, we can define our ‘collection’ of posts inside of _config.yml
and build a directory structure to suit it. Note; tabation in the below is at the correct level:
/_config.yml
collections:
web:
output: true
permalink: /web/:title
This allows us to create a directory structure such as the below:
/web/
│ index.html
└───_posts
└───jekyll
2022-06-08-realistic-use-of-collections.md
This allows the generation of example.com/web/
and example.com/web/realistic-use-of-collections
, while keeping your _posts for the category logically separated.
You already saw the sneaky use of index.html
inside of the collection dir. You can use this to create a ‘category page’ like I have below:
/web/index.html
---
layout: category
---
/_layouts/category.html
---
layout: default
---
{{ content }}
{% for category in site.categories %}
{% assign this_cat = category | first %}
{% if this_cat == current_category %}
{% for post in category.last %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endfor %}
{% endif %}
{% endfor %}
Now, for the category page to work, you’ll need to actually set the first “category” for the post to match the name of the collection. I attempted to use this post listing from aamnah, however it didn’t work. Using the categories seems to be the most reliable method of listing posts in this manner. FTR, I attempted the following code however it did not work:
{{ current_category }}
{% for collection in site.collections %}
{% if collection.label == current_category %}
{{ collection.label }}
{{ collection.link }}
{% assign name = collection.label %}
{% for post in site.[name] %}
{{ post.title }}
{% endfor %}
{% endif %}
{% endfor %}
{% for collection in site.collections %}
{% assign name = collection.label %}
<h1>{{ name }}</h1>
{% for post in site.[name] %}
<ul>
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
</ul>
{% endfor %}
{% endfor %}
There is a pretty obvious drawback here: inability to programmatically list the posts in the collection. I have tried the solutions that can be found around the web but none of them seemed to work. Infact, all my posts show up under the ‘posts’ collection, as opposed to the collection they’re really contained in.
Realistically, I think that I would opt to go back to using categories and creating a rigid category/subcategory structure. For example,
/_posts/
/_posts/somecategory
/_posts/somecategory/somesubcategory
/_layouts/category.html
/_layouts/subcategory.html
/category_pages/
/category_pages/somecategory.html
And using Permalinks to force /category_pages/somecategory.html
to render as site.com/somecategory
, and posts to render with /:categories/:title
.