I'm working on a site that essentially has posts, those posts have tags and also authors. there will only ever be one author per post.
I have the blogs working as intended as well as the tags, what I've hit a stumbling block with is relating an author key in my Frontmatter to their bio in contributors.json. Eventually this will be using Netlify CMS, so there will an "Add new author" form, then when an admin creates a new post, they can choose the author (some authors won't have access, they'll be guest contributors and just email the post over).
I can access both pages for my test authors and the correct posts are assigned, I just can't access the related data, when in the authors loop.
Anyway, my Frontmatter for authors.njk:
layout: base.njk
permalink: /authors/{{ author | slugify }}/
pagination:
data: collections.authorList
size: 1
alias: author
filter:
- all
- nav
- post
- posts
- tagList
eleventyComputed:
title: Posts written by {{ author }}
summary: "All posts written by “{{ author }}”"
Ideally, I'd need to access the data in the front matter, so I could use their actual name, as opposed to the key, in the page title etc.
A test post's Frontmatter:
title: "The fourteenth post"
summary: "A super useful post about something or other"
date: 2022-09-15
authors:
- jbloggs
tags:
- Android
- iOS
- MacOS
- Windows
In the above, my key is "jbloggs", I then have a global JSON file, like this:
[
{
"key": "jbloggs",
"name": "Joe Bloggs",
...
"img": {
"url": "/test.jpeg",
"alt": "Profile picture of Joe Bloggs"
}
},
...
]
In authors.njk, I have a card component which has a title, tags author etc and I'm correctly displaying all posts by jbloggs (I found I had to use set on a postAuthor variable and convert to JSON, as for some reason it was a JS object:
{% set postAuthor = null %}
{% for contributor in contributors %}
{% set postAuthor = contributor | toJson %}
{% if post.data.author == postAuthor.key %}
{%- set postAuthor = contributor[0] %}
{%- endif %}
{%- endfor %}
<h2>Showing {{ collections.authorList[author].length }} posts</h2>
<ul class="cards">
{%- for post in collections.authorList[author] | reverse -%}
<li class="card__item">
<article>
<h3 class="card__title"><a href="{{ post.url }}" class="card__link">{{ post.data.title }}</a></h3>
...
<span class="card__author-name">
<a href="/authors/{{ postAuthor.key }}" class="card__author-link">{{ postAuthor.name }}</a>
...
</article>
</li>
{%- endfor %}
</ul>
Then finally, the .eleventy.js file creates a collection of authors, I tried using the same functionality as the tags, but it wouldn't display the posts and some Googling got me creating a collection in this way, which would be fine, if I didn't have related data.
function filterTagList(tags) {
return (tags || []).filter(tag => ["posts", "posts"].indexOf(tag) === -1);
}
eleventyConfig.addFilter("filterTagList", filterTagList)
eleventyConfig.addCollection("tagList", function(collection) {
let tagSet = new Set();
collection.getAll().forEach(item => {
(item.data.tags || []).forEach(tag => tagSet.add(tag));
});
return filterTagList([...tagSet].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'})));
});
eleventyConfig.addCollection('authorList', collection => {
let authorSet = {};
collection.getAll().forEach(item => {
if (!item.data.authors) return;
item.data.authors.filter(
author => !['posts', 'all'].includes(author)
).forEach(
author => {
if (!authorSet[author]) { authorSet[author] = []; }
authorSet[author].push(item)
}
);
});
return authorSet;
});
What I think is happening, is the loop in the authors.njk file is converting my JSON to a js object, when it grabs the collection from config. As if I use {{ author.name }}, I get [object Object] hence why I ended up attempting to set to a new variable. I'm at that stage where I'm trying all sorts, to no avail, hence my ridiculous attempt with the new variable, so I know my I'm going about this in a complete noob type way.
What I need to do is:
But there is probably a much better way of doing this, that I am not seeing, so any help would be greatly appreciated.
Thank you
I managed to solve it, with a bit more Googling. I was over-complicating things with in my .eleventy.js file, but thanks to the chap who wrote this blog, I was able to refactor everything and got it working as I wanted.