Check out a free preview of the full Intermediate Gatsby, v2 course:
The "Add Custom Pages" Lesson is part of the full, Intermediate Gatsby, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Jason demonstrates how to build custom pages by using a special gatsby-node.js folder, which holds and exports functions, and the Node API createPages action createPage. The custom page template takes in the pageContext prop as an argument and passes over the custom set data from the context field of createPage.

Get Unlimited Access Now

Transcript from the "Add Custom Pages" Lesson

>> Now that we've got our development environment, we've got a monorepo, let's dig in and start just making some stuff. So the first thing I wanna do is I want to build a custom page, and I wanna do this without using files. Instead, I want to use the node APIs.

[00:00:17] So Gatsby has this concept of node APIs, where during the build process, it will expose hooks into different parts of the process. So there's a create pages API, a source nodes API. We're gonna look into how we can use those to customize our Gatsby site. So the first one we're gonna look at is called create pages.

[00:00:37] And the way that this works is we are going to create a new file at the root called gatsby-node dot js. And inside of this, we can export any number of hooks that we want to. And so the one that we're actually looking at first is createPages. So exports dot createPages.

[00:00:56] Now, remember this is node, so it needs to be done, or let me turn off Copilot so it doesn't, yeah. Copilot gets really confusing if I'm trying to do one thing, and it's helping. So in here, we've got the ability to export a function. And whatever we do in this function will get run as part of the create pages step of the Gatsby build process.

[00:01:23] And for us, we just wanna create our first page. So let's pull out of the actions the createPage action. And this is an object that gets passed in with various helpers. We'll use a handful of these throughout the day. I'll go into what the ones we use are, but know that's not an exhaustive list.

[00:01:44] There's more stuff you can do with the Gatsby API's. I'm gonna do the ones that are most practically useful. Some of them get a little esoteric, you can get into changing the Webpack and Babel config, which I would recommend you don't. [LAUGH] I mean you can do whatever you want, but it's gonna.

[00:02:06] Anytime you get into the internals, you're probably gonna have a bad time, unless you've got a very, very good reason for doing so. So the way the createPage API works is we're gonna pass it an object. And createPage requires three things. The first thing is a path. The second thing is a component.

[00:02:25] And the third thing is optional, which is context. So let's actually leave context out for now. So a component is gonna actually look for a file, a react component that we can use to render this page. So we need to build that. So before we save this file, let's actually go in here, and let's make ourselves a template.

[00:02:47] So I'm gonna create a folder called templates. If I can spell it, templates. And we'll call this one custom dot js. This is gonna be more of a proof of concept page. And inside of it, let's make a pretty standard react component. We're gonna import everything as React.

[00:03:05] From React, this is a workaround for React 17, not requiring the global React import anymore but Gatsby not having implemented that yet. So you have to pull in the whole library. And then we're going to export default function CustomPage. And inside of it, we can add some, let's leave that part out actually.

[00:03:31] We'll get to that in a minute. So let's return, just a basic div. And inside of it, we can say, Custom Page. All right, so now that we've got that, we can load this in. So we're gonna use require dot resolve, which is a way to get the absolute path to a component.

[00:03:54] And we're gonna use the templates custom dot js that we just created. And I'm gonna set this at a path of custom. So the path is just whatever we want it to be on the site. So slash custom will be my site dot com slash custom. And now that I've done that, if we stop and restart, because we just added a new process, we will see, and we can look at the stages in here as well as this builds as it starts.

[00:04:25] So there's these hooks here onPreInit, and onPreBootstrap, and createSchemaCustomization, and there's createPages. So when we ran createPages, Gatsby picked up our changes. And now, if we go in here and look, we can go to our custom page. And there it is. So this is a really powerful workflow, right?

[00:04:47] It lets us do a lot. But it's not particularly useful right now because this way, what's the benefit of doing this versus just creating a page called custom dot js, right? There's no real benefit here. So where the createPage starts to become extremely interesting is when we start including context.

[00:05:07] So with context, we can just pass in any object. And whatever we pass here is gonna be made available to our Gatsby site. So I'm gonna keep this pretty simple. Let's do a custom page. And then we'll add some meta stuff. So we'll do a description. And inside that, we can say, a custom page with context.

[00:05:31] And That's probably good enough, right? And then let's change this out before we restart that thing. So anything that we pass in context is gonna be available in this prop pass to the page called pageContext. And so in here, if we look at it, we can now use this to just set things up.

[00:05:55] So remember we had that title. So let's just grab that title, and use it as our page title. And then for the sake of brevity, since this is just to demonstrate the concept before we go deeper, I'm just gonna dump everything else in pageContext into a pretext so we can see what's in there.

[00:06:12] So let's save that, let's come out here, and let's restart that browser. Looks like it didn't do it. So I'm gonna stop and restart it manually. This is one of the things that can get a little tedious with doing more advanced Gatsby stuff, is when you start messing with the config files, with Gatsby node, and some of the other ones, you'll end up stopping and restarting the server a lot.

[00:06:36] So when you've got good reason to do it, absolutely, you should do it. When you, just don't opt in, voluntary suffering is my least favorite kind. So do as little as you have to, that's a motto. Let's take a look at this. So basically, what we did here is we passed in this context, and everything that we passed in, this gets passed directly as pageContext, which we can see looking at the site.

[00:07:05] Cuz this is what got dumped out of that pageContext variable. This is a really handy way to pass in information, and theoretically speaking, you could build your whole Gatsby site without ever looking at the GraphQL layer by just passing in context like this. You could load things from a third party API, drop it into this custom page context, and then use that to set up your titles and your blog role and all that stuff.

[00:07:34] It is fairly useful, but as you get into more and more complex pages, it can get pretty challenging. So, we'll look at a way to make this a little bit better as we get into some of the custom data, and see a more useful pattern for using context, and how we can kind of level that up to make things easier.

[00:07:54] The other thing that I don't like is that if we use this approach, where all the data is in context, then I don't actually know what's here until I go and look at Gatsby node. So there's a little bit of hopping between files to figure out what's available to me to use it.

[00:08:12] And I kind of prefer the the GraphQL way, where the query that shows me what data is in the file is just right up above. So this is baby steps with createPage, but let's go a little bit further here.