Skip to main content
Gatsby YAML

How to add support for multiple authors per page on GatsbyJS

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.

<Contributors contributors={contributors} />

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 (
  <React.Fragment>
   <p>
    <small>
     <i className="fa fa-users" /> Contributors:{' '}
     {contributors.map((contributor, i, arr) => {
      let lastCharacter = '.';
      if (arr.length - 1 !== i) {
       lastCharacter = ', ';
      }
      return (
       <React.Fragment key={i}>
        <Link to={`/contributors/${contributor.id}`} title={contributor.id}>
         {contributor.name}
        </Link>
        {lastCharacter}
       </React.Fragment>
      );
     })}
    </small>
   </p>
  </React.Fragment>
 );
};

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!

Related Posts

Are you interested in knowing more about GatsbyJS and JAMstack?

We can provide support. Feel free to contact us, we will be more than glad to help you.