NoSleep Javascript

How to support multiple authors in Gatsby.js

April 27, 2020 • 6 min read
#GatsbyJs#Javascript#react#filesystem#yaml#blog#GraphQL

Introduction

gatsby-starter-blog comes with out of the box support for a single author blog. But what happens when you want to support multiple authors writing in your blog?

Gatsby actually makes it very easy to do so but for people getting started with Gatsby it might be a bit of challenge putting all the parts together.

This post hopes to show how to solve this problem holistically.

This blog is actually a real life implementation of the multi author blog. Check our source!

Setting multiple author support

The highest level interface that authors writing posts will use will still be the frontmatter yaml on top of each post’s markdown file.

By specifying an author id, we are going to be able to retrieve the rest of the author data we have stored in our codebase.

content/blog/my-post/index.md
---
title: My Post!
author: author1
---

For this to work we need to setup Gatsby to:

  1. use the filesystem as a valid source of data. In this case we used src/data but it can be anything you like.
  2. use a yaml transformer because we will store our authors data inside a yaml but you could use JSON or any other format.
  3. map frontmatter’s author attribute to src/data/author.yaml.
gatsby-config.js
module.exports = {
  plugins: [
    ...otherPlugins,

    // 1. use src/data as a data source
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/data`,
        name: `data`,
      },
    },
    // 2. enable yaml support
    `gatsby-transformer-yaml`,
  ],
  mapping: {
    // 3. map author to author.yaml
    "MarkdownRemark.frontmatter.author": `AuthorYaml`,
  },
}

You will probably need to install the necessary dependencies: yarn add gatsby-source-filesystem gatsby-transformer-yaml.

Check Gatsby config docs

Important: frontmatter’s author will need to match an id attribute in your author.yaml, since that is what the mapping uses as a sort of primary key.

Now lets show how the author.yaml looks.

src/data/author.yaml
- id: author1
  bio: I am Author 1
  profilepicture: ../../content/assets/author1.png
- id: author2
  bio: I am Author 2
  profilepicture: ../../content/assets/author2.png

At this point Gatsby will automatically provide the entire Author data via the GraphQL interface, in your post template.

Notice that it will return the data for the author you specified in the post’s frontmatter, and of course, each post can have a different author.

Let’s check how the post template can use the author data now:

src/templates/blog-post.js
export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      excerpt(pruneLength: 160)
      html
      frontmatter {
        title
        author {
          id
          bio
          profilepicture {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  }
`

Inside your post component you will be able to access all author data:

src/templates/blog-post.js
export default function BlogPostTemplate(props) {
  const {
    id,
    bio,
    profilepicture,
  } = props.data.markdownRemark.frontmatter.author

  //...
}

Bonus: Author profile picture

If you look at the previous snippets you will notice we used the profilepicture to support author’s profile pictures. Notice how in the GraphQL query that we showed before we used the childImageSharp query to enable image optimization, something that the Gatbsy Starter blog does by default in the mono-author mode.

By using this childImageSharp and any of the other queries of gatsby-image you can transform dynamically loaded images via the expected GraphQL interface with ease.

How to use all authors

We’ve only covered the automagical way of mapping a frontmatter attribute to a filesystem database i.e. author.yaml.

But what happens when you want all the authors, lets say for a list of authors in your page or a shared about page?

Gatsby also has you covered with this by using the plugins we setup before. Gatsby will automatically provide a way of reading the entire author.yaml as follows:

src/pages/about.js
export const pageQuery = graphql`
    allAuthorYaml {
      nodes {
        id
        bio
      }
    }
  }
`

Notice how author.yaml is mapped to allAuthorYaml, that name transformation is significant and you should be carefully with it.

If unsure you can always go to the GraphQL explored that Gatsby provides by default and play around with the available queries.

At this point your page component will be provided with an array of authors:

src/pages/about.js
export default function About(props) {
  // this is an array of authors
  const authors = props.allAuthorYaml.nodes

  //...
}

Bonus: Run-Time multi author support through GraphQL

Notice that this setup also enables you do an ad-hoc manual implementation of the multi-author support. I will probably not recommend it for this use case but it is a possibility if you encounter a use case that might benefit from it. Notice that by using this you don’t need to statically know the author id like we did in the blog-post.js before, you can do it entirely dynamically by simply passing react props.

src/pages/Author.js
export default function Author(props) {
  const authorId = props.author
  const authors = props.allAuthorYaml.nodes

  // manually search for the selected author
  const myAuthor = authors.find((a) => a.id === authorId)

  return <p>Author Bio: {myAuthor.bio}</p>
}

export const query = graphql`
    allAuthorYaml {
      nodes {
        id
        bio
      }
    }
  }
`

And you can use it like:

<Author author="author1" />

This can be extrapolated to a lot of other use cases.

Bonus: Run-Time multi author support through importing files

And if everything else fails you can always simply import the yaml (or any other format) directly from your components and display the data however you like.

The main drawback is that you don’t have some useful image transformations and some other GraphQL-only APIs but there might be very good use cases for this approach aside from supporting multiple authors:

src/components/Author.js
import authors from "../data/author.yaml"

export default function Author(props) {
  const authorId = props.author

  // manually search for the selected author
  const myAuthor = authors.find((a) => a.id === authorId)

  return <p>Author Bio: {myAuthor.bio}</p>
}

Closing

I hope that I have eased the entry barrier for a multi author blog with Gatbsy, and taught some extra techniques in the way.



Want to become a Javascript expert? This is nice place to start:


Written by franleplant: Tech Lead and Software developer with a degree in Engineering. Woodworker, all things Javascript, Rust and Software Architecture. Github