Possum websites, done possumly

Part 5: Pagination

7 minute read time / 838 words

Let's look at paginating our post listings so we can make them more digestible when we've written many more posts.

Improving post listings

Now that we've got our post listings page outputting a list of our articles, let's get a couple more placeholder posts sorted so that we can implement our missing pagination functionality.

Go ahead and duplicate our /src/posts/2024/02/my-first-sexy-eleventy-post.njk file a couple of times and give the new files unique filenames, and fill in the titles to be unique in each page's Frontmatter. Feel free to put either or both of them in different folders if you want to. Our folder structure is going to look something like this now:

./
├── public/
│   ├── fonts/
│   └── img/
└── src/
    ├── about.njk
    ├── index.njk
    ├── posts/
    │   ├── 2024/
    │   │   ├── 01/
    │   │   │   └── my-first-sexy-eleventy-post.njk
    │   │   └── 02/
    │   │       ├── my-second-sexy-eleventy-post.njk
    │   │       └── my-third-sexy-eleventy-post.njk
    │   └── index.njk
    └── site/
        ├── data/
        ├── includes/
        └── layouts/
            ├── article.njk
            ├── base.njk
            └── posts.njk

If we visit our posts page now, we should have all those new articles listed. But they're just a bit 'meh' at the moment. They don't have a blurb, tags, or a published date and datetime. Let's fix that.

Adding dates and descriptions

Open up posts.njk and update it to look like this:

---
layout: base.njk
pagination:
  data: collections.article
  size: 6
  alias: articles
  reverse: true
---
{{ content | safe }}

<h2>Posts</h2>

<ul>
{%- for article in articles -%}
    <li>
        <h3>
            <a href="{{ article.url }}">
                {{ article.data.title | escape }}
            </a>
        </h3>

        <time datetime="{{ article.date | niceDateTime }}">
            {{ article.date | niceDate }}
        </time>

        <p>
            {{ article.data.description }}
        </p>
    </li>
{%- endfor -%}
</ul>

We'll need to add a new entry into each post's Frontmatter called description now to make that work.

---
title: My First Sexy Eleventy Post
layout: article.njk
date: 2024-01-01
tags: article
description: This is a new post, and my first ever!
---
<p>
    This is my first ever Eleventy post!
</p>

We should now have much nicer, more useful output on our post listings page, and each item will look more like this:

<li>
    <h3>
        <a href="/posts/2024/01/my-first-sexy-eleventy-post/">
            My First Sexy Eleventy Post
        </a>
    </h3>

    <time datetime="2024-01-01T00:00:00.000Z">
        Monday, 1 January 2024
    </time>

    <p>
        This is a new post, and my first ever!
    </p>
</li>

Tags

Many blogs use tags as a way to categorise posts and allow you to filter into those tags to just see articles with a specific tag. Before we can look at doing that, we need to get our posts tagged up properly, and then we can get each tag output onto the listings page too.

Firstly, open each article page, and add a new categories key into the Frontmatter. If you want to tag more than one value, you'll need to put it into an array:

categories: ['fun', 'pizza', 'eleventy']

Once complete, open up our posts.njk template and let's get these tags output on our listings page. Add this to the end of our individual item template:

{% set tagsList = article.data.categories %}


<h4>Tagged as:</h4>

<ul class="tags">
    {%- for tag in tagsList -%}
    <li class="tag tag--{{ tag | lower | replace(' ', '') }}">{{ tag }}</li>
    {%- endfor -%}
</ul>
<li>
    <h3>
        <a href="/posts/2024/01/my-first-sexy-eleventy-post/">
            My First Sexy Eleventy Post
        </a>
    </h3>

    <time datetime="2024-01-01T00:00:00.000Z">
        Monday, 1 January 2024
    </time>

    <p>
        This is a new post, and my first ever!
    </p>

    <h4>Tagged as:</h4>

    <ul class="tags"><li class="tag tag--fun">fun</li><li class="tag tag--pizza">pizza</li><li class="tag tag--eleventy">eleventy</li></ul>
</li>

More pagination

Our post listings page is currently set to do six articles per page, and once you get more than six articles it will start paginating them for you. We can add some navigation buttons to get us around those pages too.

Since we've only got three articles at the moment, let's go ahead and reduce that pagination setting from 6 down to 1 so we can see it working when it's ready.

---
layout: base.njk
pagination:
  data: collections.article
  size: 1
  alias: articles
  reverse: true
---

Now we need to add the pagination nav links to the post listings page. Go ahead and add this after the post listings in posts.njk:

<nav class="pagination">
    {% if pagination.href.previous %}
        <a class="page page--prev" href=" {{ pagination.href.previous }}">Previous</a>
    {% endif %}

    {% if pagination.href.next %}
        <a class="page page--next" href=" {{ pagination.href.next }}">Next</a>
    {% endif %}
</nav>

Refresh your posts page, and you'll now see a 'next' link at the bottom - go ahead and click it. You'll end up on page two of your listings, and you'll have a 'previous' link at the bottom which will take you back to page one of your listings.