Publishing by the moonlight.
A software development blog by Ben Szymanski.

Getting Started with Grav: Archives Plugin

As more of a general CMS than a blogging CMS, Grav ships without any built-in way to display a list of archives of blog articles. While you could hand-roll this functionality yourself, creating all of the mechanisms and architecture and presentation, there is a plugin written to do most of this for you: The Archives Plugin.

Archives on GitHub

Getting Started

The config file is located at /user/plugins/archives/archives.yaml. In it, you’ll want to make sure that the filters: category: value is set to whichever category you are using for your blog posts.

Plugins/archives/archives.yaml

enabled: true
built_in_css: true
date_display_format: 'F Y'
show_count: true
limit: 12
order:
  by: date
  dir: desc
filter_combinator: and
filters:
  category: blog
taxonomy_names:
  month: archives_month
  year: archives_year

In this example, we assume that I have all blog posts on the website associated with the “blog” category. You can assign multiple categories, separated by a comma. EX: blog, news, photoAlbums, etc…

You may also consider changing the date display format value, in which case, follow the date format specifiers list on PHP’s date reference page.

To get the archive list to actually show up on your website, you’ll need to copy then include the provided archives template.

/users/plugins/archives/templates/partials/archives.html.twig -> /users/themes/_themename/templates/partials/archives.html.twig

Inside of your site/theme templates:

{% include "partials/archives.html.twig" %}

Browsing an Archive List

At this point, you should have a basic archives list appearing in the template/sidebar of your site. Clicking on one of the archive list links is probably taking you to your homepage though, complete with a few bits of extra URL cruft.

It’s here that I ran into trouble. While the documentation covers most of the basics, it doesn’t really provide any practical examples of how to fetch a listing of an archive period and display it on a page.

What I’ve done might not be the best implementation, but it'll work.

The Set Up

First, create a template for your archive page, and then create a page using that template named Archive at /archive.

I then added the following to the Archive page’s frontmatter:

archive.md

content:
  items:
    "@page.children": "/blog"

Next, I modified the URL structure of the archive list template (provided with the plugin) to point to this page.

Templates/partials/archives.html.twig

<ul class="archives">
{% for month,items in archives_data %}
  <li>
    <a href="{{ base_url }}/archive/{{ config.plugins… }}">

So, we’re changing

{{ base_url }}/{{ config.plugins... }} 

TO

{{ base_url }}/archive/{{ config.plugins… }}

How Archives Works

One thing to note is that, how the Archives plugin actually works is that it creates new taxonomies (by default, there are two: archives_month and archives_year) (See the taxonomy_names: section of the archives.yaml config file.) On application start, the plugin hooks into the “onPluginsInitialized” event, where it iterates through every page in the CMS that is in a category defined in the filters: categories: section of the archives.yaml config file. It assigns a short-hand published date code that, by default, looks like this: jul_2017, into the archives_month taxonomy. Presumably it assigns something like 2017 into the archives_year taxonomy.

You can then use these taxonomies to query for posts and display in a browseable list-style page.

The month or year code will get passed to your page in a query string param, like this:

http://someurl/archives_month:jul_2017

Displaying Articles in an Archive Period

In a Twig template, you can access this query string param using the following:

uri.param("archives_month")

But because this is a Twig function call, it’s difficult to add it to the content: query in the page’s frontmatter.

I found the easiest way to query for the content was in the Twig template file for the archive page. For example:

templates/archive.html.twig

page.collection({'items':{'@taxonomy':{"category": "blog", "archives_month": uri.param("archives_month")}}}

You can use the collection that this returns directly in a for loop, or you could set it into a Twig template variable.

From there, iterate over the collection using a Twig for loop, displaying a list of items for that archive period.

templates/archive.html.twig

{% for blog in page.collection({'items':{'@taxonomy':{"category": "blog", "archives_month": uri.param("archives_month")}}}) %}
<div class="post-item">
    <div> 
        <h2>{{ blog.title }}</h2>
        <p><time class="date">{{ blog.date | date("F j, Y") }}</time></p>
        <p class="text">{{ blog.summary|raw }} <a class="more" href="{{ blog.url }}">Read More</a></p>
    </div>
    <hr />
</div>
{% endfor %}
Categories