Menu

Creating Gatsby pages from Drupal using the same path alias

November 9th, 2019

When looking for a way to decouple¬†your Drupal site¬†Gatsby¬†could be a great choice. It's Open Source and based on React¬†ūüöÄ. Today I'd like to show how to recreate Gatsby pages that have the same url's as¬†Drupal.¬†

JSON API

I assume that you have already setup the Drupal JSON:API and the Gatsby source drupal plugin. If not you should probably read about it at the Gatbsy blog first.

Gatsby-node.js

So assuming that you already have a working Drupal site with some basic pages let's start:

We need a title and url at least to recreate the Drupal pages. You'd probably want some content as well. In GatsbyJS we need to query Drupal for those fields. 

Start gatsby by using the `gatsby develop` command and let's go to the GraphiQL at http://localhost:8000/___graphql, we see a list of predefined queries in the Explorer window on the left. Let's use allNodePage to see all nodes from the content type 'page':

Graphql query

Copy the code from the GraphiQL editor for use in gatsby-node.js

 query AllPages {
  allNodePage {
    edges {
      node {
        title
        path {
          alias
        }
      }
    }
  }
} 

Now that we have the Drupal pages we need to create the pages in GatbsyJS. We use gatsby-node.js to query Drupal, choose a template for this content type and create a custom field `slug` which is used to mimic Drupal's path alias. 

Note that Gatsby needs a `node__` prefix for it's node.internal.type. 

The following code example is heavily based on the Drupal examples repo

 /**
 * Implement Gatsby's Node APIs in this file.
 *
 * See: https://www.gatsbyjs.org/docs/node-apis/
 */

const loc = require("path")
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const tpl_page = loc.resolve(`src/templates/pages.js`)
  const pageResult = await graphql(`
    {
      pages: allNodePage {
        edges {
          node {
            fields {
              slug
            }
            title
            path {
              alias
            }
          }
        }
      }
    }
  `)

  pageResult.data.pages.edges.forEach(({ node }) => {
    createPage({
      path: node.path.alias,
      component: tpl_page,
      context: {
        slug: node.fields.slug,
      },
    })
  })
}

exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions
  // Use the system name of your own content type from Drupal.
  if (
    node.internal.type === `node__page`
  ) {
    const slug = `${node.path.alias}`
    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })
  }
} 

Next steps could be adding more fields such as metadata, paragraphs. If you need help converting your Drupal project or have a positive comment I'd like to hear it at gatsby@guusvandewal.nl

Happy theming ūü§©

Up next: