Webiny is customizable open-source content platform for enterprises. It features a drag&drop page builder, a scalable headless CMS, digital asset manager, publishing workflows and more.

© 2026 Webiny, Inc. All rights reserved.
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:

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:
And then, we'll do the following steps to using that plugin:
gatsby-config.js file.We'll follow a simple step-by-step process to build the plugin:
We'll set up an example site and create a plugin inside it to begin building.
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.
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.
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.
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

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
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:

We've written a Gatsby plugin that:
gatsby-config.js file
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.