๐ŸŒŸย Help others discover us,ย star our GitHub repo!ย ๐ŸŒŸ

Mobile Menu

How to Create Github Contributors Plugin for Gatsby

AshutoshTwitter
September 28, 2020

In this tutorial, we'll be creating a Gatsby source plugin, which will fetch all contributors to a given Github repo. We'll also learn how to use that plugin in a Gatsby site to render a list of contributors.

Let's take a sneak peek ๐Ÿ˜‰ of what we'll get in the end:

github widget


The Big Picture:

One question that you might ask is: What is a source plugin?

Source plugins "source data" from remote or local locations into a format that Gatsby can process.

First, we'll build a plugin with the following behavior:

  1. Make an API request to the Github API.
  2. Convert the data returned by the API to Gatsby's node system.
  3. Accept plugin options to customize how our plugin works.

And then, we'll do the following steps to using that plugin:

  1. Configure our plugin in our site's gatsby-config.js file.
  2. Write GraphQL queries to access our plugin's data.

How to Create a Source Plugin for Gatsby

We'll follow a simple step-by-step process to build the plugin:

Set Up Projects for Plugin Development

We'll set up an example site and create a plugin inside it to begin building.

  1. Set up an example site

Let's create a new Gatsby site with the gatsby new command, based on the hello world starter.

gatsby new example-site https://github.com/gatsbyjs/gatsby-starter-hello-world

This site generated by the new command is where we install the plugin. It will give us a place to test the code for our plugin.

  1. Set up a source plugin

Let's create a new Gatsby plugin with the gatsby new command, this time based on the plugin starter.

gatsby new source-plugin https://github.com/gatsbyjs/gatsby-starter-plugin

This command will create our plugin in a separate project from our example site.

  1. Install the plugin in the example site

We're going to install the plugin in the example-site to make sure it works. Gatsby can only run plugins that are included in gatsby-config.js, so let's do that. Here is what the config will look like:

module.exports = { /* Your site config here */ plugins: [require.resolve(`../source-plugin`)], }

Note: Restart the development server, after changing the gatsby-config.js file. Otherwise, changes made to the config won't reflect in the project.


Source Data and Create Nodes

Now that we've setup the project for development, it's time to fill in the details.

The gatsby-node.js file is the place where the logic responsible for sourcing the data lives.

In that file, Gatsby exposes an API sourceNodes. There we'll use a Gatsby function named createNode. As the name suggests, it handles the creation of a new node.

Let's add the following code in our gatsby-node.js file:

// constants for your GraphQL Contributor type const CONTRIBUTOR_NODE_TYPE = `Contributor`; exports.sourceNodes = async ( { actions, createContentDigest, createNodeId }, pluginOptions ) => { // A Gatsby function responsible for `creating a node` const { createNode } = actions; let contributors = []; try { // loop through "contributors" and create Gatsby nodes contributors.forEach((contributor) => createNode({ ...contributor, id: createNodeId(`${CONTRIBUTOR_NODE_TYPE}-${contributor.id}`), parent: null, children: [], internal: { type: CONTRIBUTOR_NODE_TYPE, content: JSON.stringify(contributor), contentDigest: createContentDigest(contributor) } }) ); } catch (error) { console.error(error); } return; };

Now we have all the structure and logic for creating gatsby nodes in place.

Let's add the real thing, the logic for fetching real data from the Github API. We'll use node-fetch to make an API call. You're welcome to use any alternative library of your choice.

Add it as a dependency by running:

npm install node-fetch

After installing the dependency, we'll make necessary changes to the gatsby-node.js file. And after that, the code will look as follows:

const fetch = require("node-fetch"); // constants for your GraphQL Contributor type const CONTRIBUTOR_NODE_TYPE = `Contributor`; exports.sourceNodes = async ( { actions, createContentDigest, createNodeId }, pluginOptions ) => { const { createNode } = actions; let contributors = []; const repoName = "webiny/webiny-js"; // construct the API URL const githubRepoURL = `https://api.github.com/repos/${repoName}/contributors`; try { // make an API call const response = await fetch(githubRepoURL); // convert response to JSON const contributors = await response.json(); // loop through "contributors" and create Gatsby nodes contributors.forEach((contributor) => createNode({ ...contributor, id: createNodeId(`${CONTRIBUTOR_NODE_TYPE}-${contributor.id}`), parent: null, children: [], internal: { type: CONTRIBUTOR_NODE_TYPE, content: JSON.stringify(contributor), contentDigest: createContentDigest(contributor) } }) ); } catch (error) { console.error(error); } return; };

Let's restart the example-site project and visit http://localhost:8000/___graphql

Graphql

As we can see there is a new query allContributor available for us to use.

As it is, our plugin works fine. But, there is a small problem. It only fetches the contributor of a particular Github repo. And there is no way to change that value, which makes it hard to reuse by others. Let's fix this right away.

We can pass options into a plugin through a gatsby-config.js file.

Let's update the gatsby-config.js file in our example-site. We'll change the plugin from a string to an object with a resolve and options key.

After the changes the file will look like this:

module.exports = { /* Your site config here */ plugins: [ { resolve: require.resolve(`../source-plugin`), // These options will be available in Gatsby node API options: { repo: "webiny/webiny-js", }, }, ], }

Now that we've added the repo as an option to our plugin, let's update our plugin source code to use that instead of the hard coded value.

We'll make the following change:

// ... some code // use repo name from plugin options const repoName = pluginOptions.repo; // construct the API URL const githubRepoURL = `https://api.github.com/repos/${repoName}/contributors`; // remaing code is removed for brevity

Using Data From the Source Plugin in a Site

Now, our source plugin is ready. Let's use its data to render the contributors list in our example-site.

In our example-site, we'll now query data from pages.

Add the following code to file at example-site/src/pages/index.js:

import React from "react" import { graphql } from "gatsby" import "../styles/main.css" export default function Home({ data }) { return ( <div className="container"> <h1 className="heading"> Creating a GitHub contributors widget for gatsby.js </h1> <div className="grid"> {data.allContributor.nodes.map(contributor => ( <div className="contributor-card" key={contributor.id} onClick={() => { window.open(contributor.html_url, "_blank", "noopener noreferrer") }} onKeyDown={event => { if (event.key === "Enter") { window.open( contributor.html_url, "_blank", "noopener noreferrer" ) } }} tabIndex="0" role="button" > <img src={contributor.avatar_url} alt={contributor.login} className="card__img" /> <h5 className="card__name">{contributor.login}</h5> </div> ))} </div> </div> ) } export const query = graphql` { allContributor { nodes { id login contributions url type html_url gravatar_id avatar_url } } } `

Here we're using the GraphQL query allContributor to get all contributor's data. As mentioned earlier, this data is generated by our source plugin.

After making these changes our example-site home page will look something like this:

github widget


Summary

We've written a Gatsby plugin that:

  • can be configured with an entry in your gatsby-config.js file
  • requests data from an API
  • pulls the API data into Gatsby's node system
  • allows the data to be queried with GraphQL

congrats

You did it!! ๐Ÿš€ You now know how to create a source plugin for Gatsby.

You're welcome to check out the complete source code for example-site and source plugin.

If you like the post please share it on Twitter. Webiny has a very welcoming Community! If you have any questions, please join us on slack. You can also follow us on Twitter @WebinyCMS.

Find more articles on the topic of:Web developmentGatsbyGithubReactOpen source

About Webiny

Webiny is an open source serverless CMS that offers you all the enterprise-grade functionalities, while keeping your data within the security perimeter of your own infrastructure.

Learn More

Newsletter

Want to get more great articles like this one in your inbox. We only send one newsletter a week, don't spam, nor share your data with 3rd parties.

Webiny Inc ยฉ 2024
Email
  • We send one newsletter a week.
  • Contains only Webiny relevant content.
  • Your email is not shared with any 3rd parties.
Webiny Inc ยฉ 2024
By using this website you agree to our privacy policy
Webiny Chat

Find us on Slack

Webiny Community Slack