Theme

Creating a Source Plugin

In this section, we will learn to how to create a source plugin to pull data from REST API that exposes pokemon data: https://pokemon-json.herokuapp.com/.

The lesson you learnt here is transerable to any REST API that you created yourself or provided by any third-party.

Create a Local Plugin

mkdir -p plugins/gatsby-source-pokemon
cd plugins/gatsby-source-pokemon
npm init --y
touch gatsby-node.js
plugins/gatsby-source-pokemon/gatsby-node.js
exports.sourceNodes = async ({ reporter }, configOptions) => {
  reporter.info(`In gatsby-source-pokemon with the following configOptions`);
  reporter.info(JSON.stringify(configOptions));
};
gatsby-config.js
module.exports = {
  plugins: [
    'gatsby-plugin-sass',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'src',
        path: `${__dirname}/src`,
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'blogs',
        path: `${__dirname}/blogs`,
      },
    },
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: [
          {
            resolve: 'gatsby-remark-images',
            options: {
              maxWidth: 700,
            },
          },
        ],
      },
    },
    'gatsby-plugin-sharp',
    'gatsby-transfomer-sharp',
    {
      resolve: 'gatsby-source-instagram',
      options: {
        username: 'malcolm__kee',
      },
    },
    {
      resolve: 'gatsby-source-pokemon',
      options: {
        x: 'y',
      },
    },
  ],
};
npm start

Create a Source Plugin

Retrive data from API

cd plugins/gatsby-source-pokemon
npm i node-fetch
plugins/gatsby-source-pokemon/gatsby-node.js
const fetch = require('node-fetch');

exports.sourceNodes = async ({ reporter }, configOptions) => {
  reporter.info(`In gatsby-source-pokemon with the following configOptions`);
  reporter.info(JSON.stringify(configOptions));

  const pokemons = await fetch('https://pokemon-json.herokuapp.com/api/pokedex').then((res) =>
    res.json()
  );

  console.log(pokemons);
};

Create a data node

plugins/gatsby-source-pokemon/gatsby-node.js
const fetch = require('node-fetch');

exports.sourceNodes = async (
  { actions, createNodeId, createContentDigest, reporter },
  configOptions
) => {
  const { createNode } = actions;

  reporter.info(`In gatsby-source-pokemon with the following configOptions`);
  reporter.info(JSON.stringify(configOptions));

  const pokemons = await fetch('https://pokemon-json.herokuapp.com/api/pokedex').then((res) =>
    res.json()
  );

  pokemons.forEach((pokemon) => {
    const nodeId = createNodeId(`pokemon-${pokemon.id}`);
    const nodeContent = JSON.stringify(pokemon);
    const nodeData = Object.assign({}, pokemon, {
      id: nodeId,
      parent: null,
      children: [],
      internal: {
        type: 'Pokemon',
        content: nodeContent,
        contentDigest: createContentDigest(pokemon),
      },
    });

    createNode(nodeData);
  });
};

You can now query the pokemon data with GraphQL in Gatsby:

{
  allPokemon {
    edges {
      node {
        id
        name {
          english
        }
        base {
          HP
          Attack
        }
        image
        sprite
      }
    }
  }
}

Create a page to display the data

touch src/pages/pokemons.js
src/pages/pokemons.js
import { graphql } from 'gatsby';
import * as React from 'react';
import { Layout } from '../components/layout';

const AllPokemonsPage = ({ data }) => {
  const pokemons = data.allPokemon.edges.map(({ node }) => node);

  return (
    <Layout>
      <table>
        <tbody>
          {pokemons.map((pokemon) => (
            <tr key={pokemon.id}>
              <td>
                <img src={pokemon.sprite} alt={pokemon.name.english} />
              </td>
              <td>
                <p>{pokemon.name.english}</p>
                <p>Base HP: {pokemon.base.HP}</p>
                <p>Base Atk: {pokemon.base.Attack}</p>
              </td>
              <td>
                <img src={pokemon.image} alt={pokemon.name.english} />
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </Layout>
  );
};

export default AllPokemonsPage;

export const query = graphql`
  query AllPokemonQuery {
    allPokemon {
      edges {
        node {
          id
          name {
            english
          }
          base {
            HP
            Attack
          }
          image
          sprite
        }
      }
    }
  }
`;