While working on a Gatsby site, we have a requirement to provide support for multiple authors/contributors per page. We got this working by following the excellent Gatsby documentation Mapping node types.
In this post, I will be describing the steps we followed.
Adding gatsby-transformer-yaml dependency using npm
Run this on your Gatsby project within the root directory.
npm install --save gatsby-transformer-yaml
Configuring the plugins
For this example, we are going to have a contributor.yaml
file located at src/data.
- id: jane_doe
name: Jane Doe
twitter: jane_doe github: //github.com/jane_doe
drupal: //www.drupal.org/u/jane_doe
wordpress: //profiles.wordpress.org/jane_doe
linkedin: //www.linkedin.com/in/jane_doe
bio: CEO
- id: john_doe
name: John Doe
twitter: john_doe
linkedin: //www.linkedin.com/in/john_doe
github: //github.com/john_doe
bio: Technical Manager, Training and Certification
To make sure Gatsby can read this file, we need to have the gatsby-source-filesystem
installed and configured to point to a path where our YAML files are.
plugins:
[ { resolve: `gatsby-source-filesystem`,
options: { path: `${__dirname}/src/data`, name: `data`, },
},
`gatsby-transformer-yaml`,
]
Adding a map between the author field in frontmatter to the id in the contributor.yaml
objects by adding to your gatsby-config.js:
mapping:
{ "Mdx.frontmatter.author": "ContributorYaml", },
Fetching the data
After implementing this, we can fetch get all the linked authors per page using this GraphQL query.
export const pageQuery = graphql` query DocBySlug($slug: String!) { mdx(fields: { slug: { eq: $slug } }) { id code { body } fields { slug } frontmatter { title description getfeedbackform contributors { id name twitter bio avatar url } featuredcontributor } fileAbsolutePath } } `
As you can see on this query, the property contributors within frontmatter contain each one the properties of the contributor relation even when is saved as an array of string values on the markdown file.
contributors:
['contributor-id']
Showing the contributor data
We created the Contributors
component to render the data on the page template. javascript
this is the content of that component.
import React from 'react';
import { Link } from 'gatsby';
const Contributors = ({ contributors }) => {
if (contributors == null || contributors.length < 1) {
return null;
}
return (
<p><em>
Contributors:{' '} {
contributors.map((contributor, i, arr) => {
let lastCharacter = '.';
if (arr.length - 1 !== i) {
lastCharacter = ', ';
}
return ( {contributor.name} {lastCharacter} );
})
}
</em></p>);
};
export default Contributors;
Display all the posts by a contributor
Create a page template at src/templates/contributor.js
and add the following GraphQL query to pull all of the posts by contributor/author. Theme as desired.
export const pageQuery = graphql` query ContributorById($id: String!) { contributorYaml(id: { eq: $id }) { id name avatar url github drupal wordpress twitter linkedin } allDocs: allMdx( filter: { frontmatter: { contributors: { elemMatch: { id: { eq: $id } } } } } ) { edges { node { id frontmatter { title } fields { slug } } } } }
In those queries, we are filtering the data using the id
context variable. Filtering the contributorYaml
query by the contributor equal to the id
contributorYaml(id: { eq: $id })
Filtering allDocs
when the contributors
frontmatter field matches and contains id
in one of then values.
allDocs: allMdx( filter: { frontmatter: { contributors: { elemMatch: { id: { eq: $id } } } } } )
Add a GraphQL query on create-node.js
to pull all of the contributors
allContributorYaml { edges { node { id } } }
Create the contributor pages and passing the contributor id
as a context variable.
const contributors = result.data.allContributorYaml.edges
contributors.forEach(contributor => {
createPage({
path: `contributors/${contributor.node.id}`,
component: path.resolve(`./src/templates/contributor.js`),
context: { id: contributor.node.id, },
})
})
Are you interested in knowing more about GatsbyJS?
This series does not end here, so we invite you to visit our site frequently as we continue. We will be sharing some nice tips & tricks that we have learned during the development of this project.
We will be sharing with you:
- How to load templates based on your front-matter field.
- How to create page navigation based on directory structure.
- How to use the parent directory as the base.
- Finally, how to show all of the children files as clickable links to separate pages.
So stay tuned and keep on learning with us. If you want to learn more about what we do and how we may help your business, don’t think about it twice and reach out to us!