2022-07-07 — 2 min read
Tagged: jekyll

Setting Up Archive Pages with jekyll-archives

I use the pretty permalink style in Jekyll, so posts have URLs like /notes/2022/06/01/title/. What happens if we edit the URL, opening /notes/2022/?

Without any configuration, we’ll get a page not found error. If we have a 404 page, they’ll get redirected to an existing page (in my case, to the /notes/ page). With a little setup, we can generate archives for the year, month, day, category, and tag pages with the jekyll-archives gem.

Installation is the usual, add the line

gem 'jekyll-archives'

to Gemfile, run bundle, then add the following to_config.yml:

plugins:
  - jekyll-archives

The configuration depends on our needs. We can select the enabled archives, the layout(s) that should be used, and the permalink style as well. I’ll describe what I use for my site.

Since I use the pretty permalink style, I’ll need the year, month and day archives. This will make sure that when a visitor opens the /notes/2022/ or the /notes/2022/07/ or even the /notes/2022/07/01/ pages, they’ll see a list of posts published in that year, month, or on that day. I’ll also need the tags archive, it’ll generate pages for every tag I use: /tags/jekyll, /tags/ruby, and so on. I only use a single category, so I won’t need the categories archive.

Attentive readers already noticed that something is missing: jekyll-archives will generate pages for each tag, but it won’t generate a page that lists all of the tags (which should be accessible through the /tags URL). Similarly, it’ll generate pages for /notes/2022, /notes/2022/07, but it won’t generate the main archive page, /notes. We can rectify it easily, but first, let’s set up the individual archive pages.

For the above use case, we’ll need to add the following to _config.yml:

jekyll-archives:
  enabled:
    - year
    - month
    - day
    - tags
  layouts:
    year: year-archive
    month: month-archive
    day: day-archive
    tag: tag-archive
  permalinks:
    year: /notes/:year
    month: /notes/:year/:month
    day: /notes/:year/:month/:day
    tag: /tags/:name

In the layouts part I set type-specific layouts for every archive, this way it’s easier to set them up the way I want them. For example, the date archives have a title to describe the time period (Notes from 2022, Notes from 2022-07-01, etc.), but I couldn’t do that with a common layout. The layouts simply loop over the page.posts variable, which contains the posts for the given time period (or tag), here is the day-archive for example:

<h2>Notes from {{ page.date | date: '%Y-%m-%d' }}</h2>
<ul>
    {% for post in page.posts %}
    <li class="flex space-x-6 items-baseline">
        <span class="text-sm">{{post.date | date: '%Y-%m-%d'}}</span>
        <a href="{{ post.url | relative_url }}">{{ post.title }}</a>
    </li>
    {% endfor %}
</ul>

Now, back to the missing pieces: the main archive pages, /notes and /tags. Let’s create the files: /notes/index.html and /tags/index.html.

The notes index is two nested loops: once we iterate over the months that have posts, then inside we iterate over the posts of the given month:

{% assign postsByYearMonth = site.categories.notes | group_by_exp:"post", "post.date | date: '%Y-%m'"  %}

{% for yearMonth in postsByYearMonth %}
<h3>{{ yearMonth.name }}</h3>
<ul>
    {% for post in yearMonth.items %}
    <li class="flex space-x-6 items-baseline">
        <span class="text-sm">{{ post.date | date: '%Y-%m-%d' }}</span>
        <a href="{{ post.url | relative_url }}">{{ post.title }}</a>
    </li>
    {% endfor %}
</ul>
{% endfor %}

The tags index is similar, with the addition of a sorted tag list at the top:

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

<div class="flex flex-row flex-wrap space-x-6">
    {% for tag in tags %}
    <a href="{{ tag[0] | slugify }}">{{ tag[0] }} ({{ tag[1] | size }})</a>{% unless forloop.last %},{% endunless %}
{% endfor %}
</div>

<hr>

{% for tag in tags %}
<a href="{{ tag | first | slugify }}"><h3>{{ tag | first }}</h3></a>
<ul>
    {% for post in tag[1] %}
    <li class="flex space-x-6 items-baseline">
        <span class="text-sm">{{ post.date | date: '%Y-%m-%d' }}</span>
        <a href="{{ post.url | relative_url }}">{{ post.title }}</a>
    </li>
    {% endfor %}
</ul>
{% endfor %}

With these in place, we have every part of the archives covered: the main notes archive (/notes), the yearly, monthly, daily archives (/notes/2022, /notes/2022/07, /notes/2022/07/01), as well as the main tag archive (/tags) and the individual tag archives (/tags/jekyll, /tags/ruby and so on).

Thanks for reading! If you have any comments, additions, or corrections, feel free to reach me via e-mail.

Copyright © 2023 csm.hu
Contact