Pass url params through context as variables within createPage in gatsby-node

Hello,
We are trying to create a filtering system that involves passing the link resolver parameter through the context in createPage.

Is this something that is possible?

Link Resolver:

exports.linkResolver = (doc) => {
    
  if (doc.type === 'category') {
    return `/newsroom/${doc.uid}`;
  }

};

gatsby-node

const path = require('path');

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  const queryData = await graphql(`
    {
      allPrismicNewsroom {
        nodes {
          id
          url
        }
      }
    }
  `);

  queryData.data.allPrismicNewsroom.nodes.forEach((page) => {
    createPage({
      path: `/newsroom/:category`,
      matchPath: `/newsroom/:category`,
      component: path.resolve(__dirname, 'src/pages/newsroom.js'),
      context: { ...page category: ????? },
    });
  });
};

Hi Adam,

Welcome to the community!

I reached out to the Gatsby experts on our team and this is the response I got.

Gatsby recommends creating pages statically unless a page needs dynamic information that cannot be determined at build time. In the case of a “newsroom” section of a site, all of the content should be available at build time, so the pages can be built statically.
The code shared above uses client-side rendering (not static rendering). Using the matchPaths option in createPage() opts out of static rendering, meaning the entire page will need to be rendered in the browser when a user requests it. This will result in a slower site, so it is not recommended unless completely necessary.
To build the newsroom category pages statically, you would use this code instead:

// gatsby-node.js

const path = require("path");

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  const queryData = await graphql(`
    {
      allPrismicNewsroom {
        nodes {
          id
          url
        }
      }
    }
  `);

  queryData.data.allPrismicNewsroom.nodes.forEach((node) => {
    createPage({
      path: node.url,
      component: path.resolve(__dirname, "src/pages/newsroom.js"),
      context: {
        id: node.id,
      },
    });
  });
};

Note that you can pass node.url to the path option. node.url will look something like /newsroom/company since that is the path returned by your Link Resolver function. The PrismicNewsroom node’s ID will be passed via context. In the src/pages/newsroom.js file, you’ll have access to this ID to query the node again (notice the $id variable in the GraphQL query). You should query for all of your newsroom category’s data in the page component, not in gatsby-node.js.

// src/pages/newsroom.js

import * as React from "react";
import { graphql } from "gatsby";

const NewsroomCategoryTemplate = ({ data }) => {
  const category = data.prismicNewsroom;

  return <div>{/* Render your content here */}</div>;
};

export default NewsroomCategoryTemplate;

export const query = graphql`
  query NewsroomCategoryTemplate($id: String!) {
    prismicNewsroom(id: { eq: $id }) {
      data {
        name {
          text
        }
        # The rest of your PrismicNewsroom fields
      }
    }
  }
`;

Gatsby supports a nicer way of generating pages than this. Rather than using gatsby-node.js to generate pages, you can use your page’s filename to generate them.
To do this, remove all the code in gatsby-node.js (if you aren’t using it for anything else, you can delete the file), and rename the page file to src/pages/{PrismicNewsroom.url}.js. Now Gatsby will automatically generate a page for each newsroom category. It will provide the $id context variable in the GraphQL query automatically. You can learn more about this method here: File System Route API
If your app actually needs to be rendered on the client for some reason, let me know and I can provide an example of setting up the necessary routing and URL parsing. Gatsby has a page with more information here: Client-only Routes & User Authentication

Thanks.

Hey @Phil
Thanks for this response!

One little thing I left out that could throw a wrench into it.
We are passing the categories as a repeatable content type through a content relationship on the Newsroom Article page.

Then the Newsroom page itself is filtering those individual articles by the category that is assigned.

Hey Adam,

In that case, you'll use the filter argument in Gatsby to get it by the category and Paulina shows in this example:

Thanks.