We will learn how to fetch page data from the Notion API, and build a static recipe website. We start with a page containing a list of recipes - each a link to its own recipe page - and use Next.js to create a pre-generated page listing our recipe titles.
In order to request data from our Notion API, we create a new integration and share the data from with page with it. We also learn about how to manage secret environment variables in our Next.js application, and how to conveniently pretty print the results from the
Lastly, we take the raw Notion data and transform it into a convenient array structure, that we can iterate over in our page component, and display in the browser.
Instructor: [0:00] Here, I have a Notion page that's a list of recipes. Each of these recipes has a list of ingredients and a method. To make this data available to our Next.js application, we need to create an integration.
[0:11] If we head over to the menu here and come down to Settings and Members and then down to Integrations at the bottom here, we can then click this link to develop our own integration.
[0:20] We want to create a new integration, and we are going to call this Recipes. We also need to specify a logo. I am going to upload an image for Recipes, which is going to be this frying pan. I want this associated with my Notion API course workspace, which is the workspace that contains my page with the list of recipes.
[0:39] Now, we can click Submit, and that has created us a new secret token for this integration. If we click Show and then Copy, we can bring this over to our Next.js application, create a new .env file. Now, we can create a new environment variable for our Notion secret, and we can dump that value in there.
[0:58] The other environment variable we need is page ID. We can get that from our URL for our page. We ignore this first part, this recipes-, we just want to get everything after the dash and copy that into our .env file.
[1:12] The last thing we need to do is actually share the data on this page with our new integration. If we click share and then click here to invite our integration, click recipes and then invite.
[1:23] Our integration will now be able to make requests for any of the data on this page as well as any of the nested pages within it. Back over in our Next.js application, we would like to create a new page for our recipes.
[1:35] We can then open up our new page and create a basic page component. Now we can run our server again and open up our new page by going to localhost:3000/recipes. We should see that H1 there.
[1:51] Now we can export out our getStaticProps function. This is going to be an async function, as we're going to have to wait for that data to come back from Notion. To fetch data from our page, we need to install the Notion client library.
[2:05] I'm going to quit my development server and type npm install @notionhq/client. Once that's finished installing, we can run our dev server again and import that new package.
[2:17] Now we can create a new Notion client. We just need to pass that a configuration object with the key auth set to process.env.notionSecret. Now we can get a list of the blocks that exist on our page by saying notion.blocks.children.list. Again we need to pass a configuration object, but this time with the key block_ID. That is going to be set to process.env.pageID.
[2:51] This is going to give us back a promise, so we want to create a new variable to hold that data. We want to wait for that promise to resolve.
[3:01] If we want to see what this data looks like, we can return an object with the key props, which is another object. Inside that we have a key for recipes and we can set it to data.
[3:12] Then remember, this props object gets passed into our page component. We can just destructure recipes here. Instead of our H1, we can render out a pre-tag. Then in here we can say JSON.strinfigy and dump out our recipes.
[3:29] Now if we save this and refresh we'll see this big long JSON blob all on one line. Now with JSON.stringify we can pass an additional parameter of null and then the number two. This is just going to pretty print this out so it's a little more readable.
[3:44] If we have a look at the structure of this, it's one big JSON object with a key of results. That's an array of a whole bunch of objects. In each of those objects you'll see this first one has a type of unsupported.
[3:54] The next one has a type of child page and a title of "Pasta Pesto." The next one is also a child page and has the title, "Tuna Noodle Casserole."
[4:02] If we have a look at our Notion page, that's the same structure here. This templated button here was the thing that was unsupported. Then each of these is a child page that contains one of our recipes.
[4:13] We basically want to ignore this first object and then take each of the objects after it and pull out the title. Let's start with an empty array of recipes. We then want to take the data.results array and we want to iterate over each item in that collection. For each of those results, we want to check whether the result.type is equal to childPage.
[4:37] If that's the case we want to push a new recipe into our array. The title of that recipe is going to be under result.child_page.title. Now instead of returning our initial results, we just want to return our new array of recipes.
[4:55] If we come over to our browser and refresh, we'll see that all of our recipe titles have been piped through to our component. Rather than just dumping out our array into the DOM, we can get rid of this and iterate over each one of our recipes.
[5:09] For each recipe we can render out a paragraph tag that just contains that recipe. Now when we hit Save you'll see that each one of our recipes is displayed in its own paragraph tag.