Check out a free preview of the full Intermediate Gatsby with Gatsby Themes course:
The "MDX Nodes" Lesson is part of the full, Intermediate Gatsby with Gatsby Themes course featured in this preview video. Here's what you'd learn in this lesson:

Jason demonstrates how to create MDX nodes using the onCreateNode hook, and explains that nodes are data structures in Gatsby.

Get Unlimited Access Now

Transcript from the "MDX Nodes" Lesson

[00:00:00]
>> Jason Lengstorf: Now we wanna actually create these nodes. And to do that we're going to listen for any MDX node that gets created, and then we'll create a docs page node out of it. So to do that, we're going to add another API hook, and this one is called onCreateNode.

[00:00:18] And this one gives us a bunch of data. So the first thing that's gonna give us is the node that was created. It'll give us an object for the actions that we can do that will help us kinda process this node. It will give us the ability to load the content of a given node.

[00:00:32] So if we wanna get it to parent or if it had children, we could get those and it'll give us a helper to create a node ID. And finally, it'll give us options. So inside of this, we are going to start by getting out just the options that we need.

[00:00:50] So we wanna use the base path in here, because we're going to set the path for the docs page to be, it's going to include that base path if necessary, cuz this is how it will actually build the pages later, using this path. So we're gonna pull the base path out and we'll use the defaults.

[00:01:12] Okay, and then we're gonna load the parent node. So when we get an MDX node, that MDX node is generated off of a file node. So the way that Gatsby works is the Gatsby source file system creates file nodes. And then Gatsby plugin MDX is actually a transformer plugin.

[00:01:31] So what it's doing is it's looking for any file nodes. And then it checks the type actually using this onCreateNode API that we're looking at right now. And if it finds compatible types, which in this case would be files with a mdx extension, it will then create a child node for the file called child MDX.

[00:01:50] And that is what we are receiving here is the child MDX. So, we wanna load that file so that we can check that name. Remember, we set the name for the files to Gatsby themed docs. And that's because we only want to create docs pages for docs that are loaded by this theme.

[00:02:08] We don't want to turn blogs or anything else into docs pages. So we're going to get the node, which is the node.parent. And then we wanna make sure that we only work on MDX files that were loaded by this thing. And to do that we set up an if statement.

[00:02:32] And the first thing we're gonna check is that the actual type of this node is MDX. And in Gatsby, the internal is just kind of metadata about a given node, and the node.internal.type is going to reflect whatever the plugin told it the data type was. So if it's a file, the internal type would be file.

[00:02:54] If it's Mdx, Mdx uses this capital M lowercase dx as its file type. We're gonna be using docs page as our file type. So we can just check and say, hey, I only wanna work on Mdx files or Mdx nodes, so if we don't have any bail out.

[00:03:09] And then the other thing that I wanna check is if the parent source instance name is not actually Gatsby theme docs. And again, I should have made this not. So what we're doing is we're doing an early return. So what we’re saying is, if the node type is not Mdx, or the source instance name of the file gatsby-theme-docs.

[00:03:39] That source instance name comes from here. So whatever we set as the name in Gatsby source file system, that will become the source instance name on the file node. So when we load that parent, the parent is a file node, and we can check to make sure that it was loaded by our theme, and not some other file.

[00:03:59] So if those things aren't true, we're gonna bail out. But once we get to here, we know that our node is an Mdx node that was loaded by our theme. So that means we can start to customize it. So the first thing I'm going to do is I wanna make sure that if we have an index file, we wanna treat an index index dot MDX, the same way that we would an index dot HTML.

[00:04:24] And what that means is we want it to load up at docs Instead of docs index, which would be the default behavior. So we're gonna set up a page name. And the page name that we'll use is if the parent name is not index, we will use the parent.name.

[00:04:51] And if it is index we'll leave it blank. In that way it would just be the content or the base path. So if we go /docs and have an index .Mdx there will be /docs and that will be the URL. And if we have an about.Mdx it will be /docs and /about.

[00:05:11] Because the parent.name is the file name without an extension. So we have our page name and from there I'm gonna go ahead and use the create node action and that accepts an objects which is our new node. So the first thing I wanna do is create a node ID.

[00:05:30] And the node ID can be arbitrary, it just needs to be unique. So what I typically do is I take the type that we're going to use, and then I take the existing nodes ID, and pass that into create node ID. And that'll create a unique hash. So the the idea is already unique, but then by adding our type to it, we get a new but also unique hash.

[00:05:54] Once I've got the ID, I can add in the title. And so the title is gonna come out of the front matter. But if that's not set, we can just fall back to the file name. We're gonna check the updated time and fortunately, Gatsby's file system will just give us that, so we'll do parent modified time.

[00:06:16] And that's the last time that that file was modified, so that's nice and handy. Then, I wanna get the path and I'm gonna use the path module. Make sure I've got that included up here, I do. So I'm gonna use path.join and I always wanna start with a leading slash so we'll include that in there.

[00:06:36] Then I'm gonna use the basepath. And then I'm gonna use the relative directory of the parent. And what that means is like in our docs, we could set up /docs/react/hooks. State management or something, and the URL will reflect the directory structure inside of our content path. So that makes it a little more logical for people who are managing content.

[00:07:05] Whatever the folder structure looks like in the content will be what gets reflected on the URL and in the hierarchy of the site. And once you've got that relative directory in there, we will include the page name, whoops. Skip to the beginning of the folder, page name. So this now is our only collapse out.

[00:07:25] So we can see the whole thing. So our path then is going to be starting at the leading slash. If we have a base path like /docs, then the relative directory to match the file hierarchy. And then the page name which will either be the filename or empty if its index.

[00:07:42] So, does this make sense? Does anybody have questions about how this works before we move on?
>> Speaker 2: So I guess just to clarify, the purpose of what we're doing here is creating knows that we can query and GraphQL.
>> Jason Lengstorf: Exactly.
>> Speaker 2: Okay.
>> Jason Lengstorf: Yeah, so what we're doing is we're basically saying we define this docs page up here.

[00:08:03] Id titled path updated. And in onCreateNode, id title path updated, we're creating all these files.