In our last step, we got our site up on Netlify, presumably, so the world can see our site.
In this step, we're going to build a "posts" index page, accessible at /posts
,
that lists all of our posts, with their tags, and the newest post at the top of
the list.
The Page, Sans Posts
First, we just need a page that lists our posts. But in order to do that, we just need a page.
Create content/posts.njk
with the following content:
---
title: All Posts
description: All the Posts Worth Posting
layout: "layouts/base.njk"
---
<h2>Here is where our posts will be</h2>
<p>... once we figure that out</p>
Now we can head to localhost:8080/posts
to check it out!
The page renders, though it has no posts on it. Let's fix that.
A Note about Collections
Eleventy handles groups of related content through the Collections
API. We have a default collection of
all
, but also when we apply tags to posts, those posts get added into
tag-specific collections (like posts
or Eleventy
. The collections are just
data compiled during the build process, and are used to build pages.
We can also build collections dynamically from data (on our file system, from a remote API, generated at will by some code, etc.) during the build process, though we won't worry about that right now.
For now, what we need to know is that we can access all pages with a posts
tag
applied through collections.posts
in our JS and in our NJK templates.
The next steps require that you've got 1 or more posts with "tag: posts" in the front-matter. If you haven't done that yet, please do so.
Getting Our Posts onto the Page
Open up content/posts.njk
again, and replace the filler body (everything below
the YAML front-matter) with this:
<ul>
{%- for post in collections.posts -%}
<li>This is a post</li>
{%- endfor -%}
</ul>
The for-each
loop should look familiar to you if you've done some coding
before. The {%- -%}
NJK tag pair indicates that this line doesn't render or return, but
does execute. We've already seen {{ some value }}
, which indicates that the
result of the expression gets interpolated right into the page.
When we refresh the page, we should see:
<ul>
<li>This is a post</li>
<li>This is a post</li>
<li>This is a post</li>
<li>This is a post</li>
</ul>
Or something like it, with one <li>This is a post</li>
for each post in our
collection.
What we actually want, though, is the post title. Let's replace our hard-coded
value with the post title. Since we have our post
object, we can view data
about that post as post.data
, and the title as post.data.title
<ul>
{%- for post in collections.posts %}
<li>{{post.data.title}</li>
{%- endfor -%}
</ul>
This is pretty good. We can make it even better by adding the URL.
<ul>
{%- for post in collections.posts -%}
<li>
<a href="{{post.url}}">{{post.data.title}}</a>
</li>
{%- endfor -%}
</ul>
Now we have a list of posts, in chronological order (oldest first) by date, with clickable links!
What About Newest First?
Imagine we want to show the newest posts first, instead of the oldest. We can do that!
<ul>
{%- for post in collections.posts | reverse -%}
<li>
<a href="{{post.url}}">{{post.data.title}}</a>
</li>
{%- endfor -%}
</ul>
The |
operator basically the same as the Unix pipe operator; it passes the
thing on the left to the function on the right. So we pass collection.posts
to
reverse
, which just returns the reversed list. With this change, our posts now
appear in reverse chronological order.
Just make sure we don't use
.reverse()
or other JS methods that mutate the list in place. Using something like
Nunjuck's reverse
filter (a pure function) is a much better choice.
Wrapping Up
Once we save and commit, we'll have a page that lists all of our posts. Cool!
What's Next?
We should probably introduce some styling at some point.
We should probably also do a better treatment of filters and collections, and maybe think about tasks like "Show the most recent 3 posts on the home screen" or "List all posts by tag".