gatsby-node.js

The gatsby-node.js does the heavy lifting for building the docs pages from the table_of_contents.json.

To understand the gatsby-node file in general, read this first.

In our case, we are implementing two of these APIs by default: onCreateNode and createPages. I recommend reading their docs and examples linked there.

onCreateNode

The onCreateNode hook is called when a node is created. Nn this case we are trying to add a field for the slug on each MarkdownRemark node. This slug is useful for the querying and filtering that we use in the doc.jsx template. So first, we grab each node that has been created from our gatsby-transformer-remark created nodes from the gatsby-source-filesystem, like this:

  if (node.internal.type === 'MarkdownRemark')

Once we have that node, we are going to use a process described in the Gatsby docs for adding the slug field mentioned above. A link to that method is here. In our case, we will also be testing the Markdown file for a title or slug that has been defined in frontmatter, and using that first.

if (node.internal.type === 'MarkdownRemark') {
  const fileNode = getNode(node.parent);
  const parsedFilePath = path.parse(fileNode.relativePath);
  if (
    Object.prototype.hasOwnProperty.call(node, 'frontmatter') &&
    Object.prototype.hasOwnProperty.call(node.frontmatter, 'slug')
  ) {
    slug = `/${_.kebabCase(node.frontmatter.slug)}`;
  }
  if (
    Object.prototype.hasOwnProperty.call(node, 'frontmatter') &&
    Object.prototype.hasOwnProperty.call(node.frontmatter, 'title')
  ) {
    slug = `/${_.kebabCase(node.frontmatter.title)}`;
  } else if (parsedFilePath.name !== 'index' && parsedFilePath.dir !== '') {
    slug = `/${parsedFilePath.dir}/${parsedFilePath.name}/`;
  } else if (parsedFilePath.dir === '') {
    slug = `/${parsedFilePath.name}/`;
  } else {
    slug = `/${parsedFilePath.dir}/`;
  }
  createNodeField({ node, name: 'slug', value: slug });
}

You really should not need to mess with this unless you want to alter the way your slugs are defined.

createPages

This hook fires after all source and transforming has been done on the nodes and allows you to query that data and build pages with it.

First, we tell Gatsby the template we want to use for these pages, in our case it's our doc.jsx page.

const docPage = path.resolve('src/templates/doc.jsx');

In this portion of the code, we are querying our data for the information we need to build the page:

    resolve(
      graphql(
        `
          query {
            allMarkdownRemark {
              edges {
                node {
                  frontmatter {
                    title
                  }
                  fields {
                    slug
                  }
                }
              }
            }
          }
        `
      )

In its callback, we are looping over each Markdown page that returned from the query and using Gatsby's native createPage function to create the page, and referencing the template we defined above:

result.data.allMarkdownRemark.edges.forEach(edge => {
  createPage({
    path: edge.node.fields.slug,
    component: docPage,
    context: {
      slug: edge.node.fields.slug,
    },
  });
});

This createPages can definitely be modified to pass more information from the Markdown to the React template.