New site part 3 - individual posts
Posted on 04 October, 2023
Part of a series about setting up the new 11ty version of this site
I'm going to do some (slightly) clever things with my collection of posts later, but first I need to work out how I'm going to write an individual page.
Collecting posts
I'll organise individual posts within my src/posts/ folder by year and month, but I want the
permalink for each to only be based on the title of the post. I also want there to be "next post" /
"last post" links for each individual post, so I need a unique layout.
So first thing to do is add a file posts.11tydata.js in my src/posts/ folder, which means I can
set common front matter for all my posts:
// src/posts/posts.11tydata.js
module.exports = {
permalink: "/{{ title | slugify }}/index.html",
layout: "layouts/posts.njk",
tags: ["post"]
}
This gives me a permalink based on the slug of the post's title, uses a new posts.njk layout (that
we'll need to write), and makes a new 11ty collection called post.
Config
I want to make sure that my posts are sorted in reverse chronological order (most recent post first) which means defining the collection:
// eleventy.js - inside module.exports
module.exports = function(eleventyConfig) {
...
// reverse the order of post collection
eleventyConfig.addCollection('post', (collection) => {
return collection.getFilteredByTag("post").reverse();
});
...
}
Laying it out
- First we need, for 'this' post, to find out what the previous and next posts are.
// src/_includes/layouts/posts.njk - pt 1
---
layout: layouts/base.njk
---
{% set nextPost = collections.post | getNextCollectionItem %}
{% set previousPost = collections.post | getPreviousCollectionItem %}
- Some boilerplate layout, plus the post title (class names hopefully self-evident). This includes the content of the post, and the opening of the 'next/previous' element.
// src/_includes/layouts/posts.njk - pt 2
<div class="container">
<div class="row">
<div id="main-content-grid">
<div id="main-content">
<div class="post-title-header">
<h1 class="post-title as-h2">{{ title }}</h1>
</div>
<p class="post-date">
Posted on <span class="date">{{ date | postDate }}</span>
</p>
{{ content | safe }}
<div class="next-previous">
- The 'next post' link. We have to use the previous post (because we've reversed the order), and I'm testing to make sure that there is a previous post. I've removed indent for easier reading
// src/_includes/layouts/posts.njk - pt 3
{% if nextPost %}
<p>Previous <a href="{{nextPost.url}}">{{nextPost.data.title}}</a></p>
{% else %}
<div></div>
{% endif %}
- And the 'previous post' link. Unsurprisingly we need to use the next post in the collection.
// src/_includes/layouts/posts.njk - pt 4
{% if previousPost %}
<p class="right">Next <a href="{{previousPost.url}}">{{previousPost.data.title}}</a></p>
{% else %}
<div></div>
{% endif %}
- And finally, wrap up the boilerplate.
// src/_includes/layouts/posts.njk - pt 5
</div><!-- close the next-previous element>
</div><!-- close the main-content element>
</div><!-- close the main-content-grid element>
</div><!-- close the row element>
</div><!-- close the container element>
Writing a post
My posts will be written in markdown; although I'll keep a year and month folder system to help organise them, the year, month and indeed filename aren't actually important — the permalink I set out above doesn't use any of them.
I've decided that I'll have some standard front matter in each file — a title (which I need,
since it's used to generate the unique permalink), a date (used to sort the post collection)
and some kind of content tagging that I'm choosing to call categories.
// example front matter for a post
---
title: Technical Sophistication
date: "2016-10-04"
categories:
- thoughts
---
// content here in markdown