Dynamically generating Gatsby pages with a headless CMS: what's the trick?

I’m working on a project where I’ve got a headless CMS built with Django as my backend. I want my Gatsby frontend to create pages automatically based on content from the CMS. I’ve set up GraphQL with Graphene to expose the Django data, but I’m stuck on how to fetch the slugs and use them in gatsby-node.js to generate pages.

Here’s what I’ve tried so far:

// gatsby-node.js

exports.createPages = async ({ graphql, actions }) => {
  const result = await graphql(`
    query {
      allCmsPages {
        nodes {
          urlPath
        }
      }
    }
  `);

  const { createPage } = actions;
  const pageTemplate = require.resolve('./src/templates/cmsPage.js');

  result.data.allCmsPages.nodes.forEach(node => {
    createPage({
      path: node.urlPath,
      component: pageTemplate,
      context: { slug: node.urlPath },
    });
  });
};

This code isn’t working as expected. How can I properly fetch the slugs from my CMS and use them to create Gatsby pages? Any tips or best practices for this kind of setup?

hav u tried using the createResolvers API? it can help u fetch data from ur CMS during build time. u could do smthing like:

exports.createResolvers = ({ createResolvers }) => {
createResolvers({
Query: {
allCmsPages: {
resolve: async () => {
// fetch data from ur CMS here
}
}
}
})
}

this way u can get ur slugs b4 createPages runs. hope this helps!

hey there! have u considered using gatsby-source-graphql plugin? it can make fetching data from ur django CMS way easier. u could set it up like this in ur gatsby-config.js:

plugins: [
  {
    resolve: 'gatsby-source-graphql',
    options: {
      typeName: 'DJANGO',
      fieldName: 'django',
      url: 'http://yourdjangoapi.com/graphql',
    },
  },
]

then u can query ur CMS data directly in gatsby-node.js. what do u think?

Your approach is on the right track, but there are a few tweaks that could help. First, ensure your GraphQL schema in Django is correctly exposing the data you need. Then, in your gatsby-node.js, add error handling and data validation. Here’s a refined version:

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;
  const pageTemplate = path.resolve(`./src/templates/cmsPage.js`);

  try {
    const result = await graphql(`
      query {
        allCmsPages {
          nodes {
            slug
          }
        }
      }
    `);

    if (result.errors) throw result.errors;

    result.data.allCmsPages.nodes.forEach(node => {
      if (node.slug) {
        createPage({
          path: `/${node.slug}`,
          component: pageTemplate,
          context: { slug: node.slug },
        });
      }
    });
  } catch (error) {
    console.error('Error creating pages:', error);
  }
};

This handles potential errors and ensures each slug is valid before creating a page. Remember to adjust the GraphQL query if your CMS uses a different field name for slugs.