Last time we did quite a bit of work on our site to make it come together. At this point, I think it's time we talk about Data in Eleventy.
But first, let's improve the flow on our blog posts by adding next and previous post links to the bottom of our posts.
Adding Next/Previous Post Links
Let's start by adding a third post in our blog folder.
Now we are going to implement what is called layout chaining in Eleventy.
We will start by creating a partial for our pagination. Yes, this is pagination (I have an article planned for this concept, but later).
In _includes/partials
create a paginate.njk
and place this in it:
{% set previousPost = collections.post | getPreviousCollectionItem(page) %}
{% set nextPost = collections.post | getNextCollectionItem(page) %}
{% if previousPost %}Previous: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a>{% endif %}
<br>
{% if nextPost %}Next: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a>{% endif %}
In the snippet above, we introduce a new feature of Eleventy - set
. Set is used when we want to create a specialised piece of content that is not present in our site.
- We create a previousPost and nextPost that relates to our post collection
- Then we make an if statement to check if these exist in our collection.
- If they do, output the URL of that post otherwise display nothing.
Then in _layouts
make a new file called blogLayout.njk
and place this in it:
---
layout: base
---
{{content| safe}}
<br/>
{% include "partials/_paginate.njk" %}
<br>
<hr>
<a href="/blog">Blog Home</a>
Next, we change the layout key in the frontmatter of our post files to this:
title: First Post
layout: blogLayout # modify this line
tags: post
We are switching the layout we use for posts to the one we just made - this is where we've chained layouts. A post uses the blogLayout which uses the base layout.
Permalinks
Permalinks are another feature of Eleventy(that I forgot 😁) that allows you to determine what a pages' URL becomes
Say for example you chose to place your page files in a pages directory, but didn't want them to be output as [your_site_url]/pages/about_page
but as [your_site_url]/about_page
, this is where permalinks come in:
# src/pages/about.md
---
layout: base
title: About
tags: page
permalink: /about/
---
Eleventy Data Cascade
Eleventy'a data cascade refers to the order in which Eleventy renders site data.
The closer (more specific) data is to content, the higher priority it has
That cascade, in order of priority is:
- Computed Data - data derived from other data
- Frontmatter Template Data - in a single template
- Template Data Files - Applied to one file
- Layout Frontmatter Data - Applied to all templates that use that layout.
- Directory Data Files
- Configuration Global Data
- Global Data Files
When we make use of this data, it is usually in reverse order, with global data first, then config data and so on...
When I say template, it just means any file with content
Currently we have used two type two kinds of Eleventy data
- Layout Template Data - when we rendered the navigation and post list
- Front Matter Data - the title frontmatter in our pages
Let's make use of some of the other types of data
Global Data Files
If you recall when we set up our project, we did this in our .eleventy.js
return {
dir: {
input: "src",
data: "_data", //take note of this
includes: "_includes",
layouts: "_layouts",
},
};
Global data refers to files we place in the _data
folder. In most instances we use global data for things we want site wide, for example the site title and description.
Let's make a global data file to house some of our site data.
Make an _data
folder in src and in in a site.json
and place this in it
{
"title": "James Midzi",
"description": "A site to showcase Eleventy features by building a site.",
"keywords": "eleventy, 11ty, css, ssg"
}
This will give us some global configuration options that will be used on the site.
Now, we will modify the head tag in base.njk
to
<title>{{site.title}}{% if title %} - {{title}} {% endif %} </title>
<meta name="description" content="
{% if description %}
{{description}}
{% else %}
{{site.description}}
{% endif %}
"/>
Above, we are running checks to see if the title and description data exists in our pages (templates), if it does render it. Otherwise, use the data in site.json (global data)
The final head tag should look like this:
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- stylesheet -->
<!-- <link rel="stylesheet" href="{{ '/assets/css/style.css' | url }}"> -->
<link rel="stylesheet" href="{{ '/assets/css/tailwind.css' | url }}">
<!-- Meta -->
<title>{{site.name}}{% if title %} - {{title}} {% endif %} </title>
<meta name="description" content="
{% if description %}
{{description}}
{% else %}
{{site.description}}
{% endif %}
"/>
</head>
NOTE: our data files can be json or javascript
The changes we have made will help with our site SEO
Config Global Data
I at present do not know the correct way to apply global config data. I will continue researching and asking questions. I will revisit this part when I have a better understanding of this.
Directory Data Files
These set data on a folder level, and they must be named the same as the folder they are in.
They apply data in it to everything contained in that folder.
Let's take a look at our posts. We are currently setting this in each post's frontmatter
---
title: First Post
layout: blogLayout
tags: post
---
While this might be fine now, imagine if we added more posts. We would have to copy this frontmatter pattern into each of them.
A Data Directory File helps us with this repetition problem. Let's do that, shall we?
In the src/blog
folder, create a blog.json
file and place this in it
{
"layout": "blogLayout",
"tags": "post"
}
With this done, we can remove the layout and tags from our post files so they now look like this:
---
title: First Post
description: This is my first post
---
Checking our site, we can see that everything is still working. Now, if we add more posts, we only have to be concerned with the title and description.
NOTE: Remember to restart your dev server
Template Data Files
This data is applied on a file(template level) where if you had a about.md
you can have data that applies only to it in a about.11tydata.js
or about.11tydata.json
Computed Data
For the life of me, I can't figure out how one would go about using computed data. But I believe someone in the Discord will be able to help. As with Config Data, I will return.
An Intermission
That was a lot right? Yeah, I know. But at least we have now covered some of the more involved parts of Eleventy and how you can make them work for you.
Conclusion
This has been one of the more longer tutorials of this series. I hope you all stayed till the end because understanding how data works will greatly improve how you build your Elevnety site.
In this article we:
- Added pagination to our posts
- Added a data file to manage site metadata (we will build on it later)
- Added a directory data file to simplify the creation of new posts.
- Talked about the data cascade in Eleventy.
As always:
- The working repo: Part 4: Data
- The docs: https://www.11ty.dev/docs/
- The discord: https://www.11ty.dev/blog/discord/
Thank you for reading, let's connect!
Thank you for visiting this little corner of mine. Let's connect on Twitter, Polywork and LinkedIn
Top comments (5)
I had a problem with the layout chaining, the front matter was not being evaluated. It seems it doesn't like indentation, there are some spaces in front of some code chunks in the tutorial. So the issue was me copying the code instead of typing it out by myself. Just a heads up :)
Thank you James for these writings on 11ty!
Thank you for going through the series!
Oh, that's interesting... it's probably because I copied directly from my editor and pasted without stripping the formatting - thank you for the catch :-)
Have just explored 11ty and this series, good thing I scrolled to the comments and found this, thanks!
Thank you for doing through the series
Just a heads up to anyone following this and is using Liquid instead of Nunjucks (and to save you a bit of Googling):
Liquid does not have a
set
tag, it's calledassign
. And it does not allow parenthesis, so for the Next / Previous posts links you'll have to replace the code with the following: