DEV Community

loading...
Cover image for How to use Notion API with NextJS

How to use Notion API with NextJS

Georgey
Looking forward to connect with web devs around the world! Engineer || Content-Writer || Athlete
Originally published at geobrodas.vercel.app ・6 min read

Notion API is finally here, and it's so cool. But you must be wondering what is Notion in the first case? Well, it's a powerful productivity tool for managing your daily day-to-day tasks, or maybe jotting down a lot of ideas you want to put up in your next blog? There are unlimited possibilities.

I myself found it annoying at first because I have a habit of writing down things instead of typing them out on a notepad. But turns out, it did boost my productivity moreover, it's much more noticeable when you are working with a team.

Now imagine if you could display all these data to a front-end, and update them directly on the Notion database instead of pushing some extra line of code. Your favorite tool now has its own API!

This tutorial is beginner-friendly, so don't hesitate. I assure you, the result is satisfying.

Here are the steps we'll be going through,

  1. Create a new database on Notion.
  2. Making a new integration.
  3. Setting up the back-end.
  4. Fetching data from the database.
  5. Modifying the API call.
  6. Displaying the data on a NextJS project.

Source code: GitHub


Create a new database on Notion.

Go ahead and make a new Notion account, if you haven't made one.

Create a new page.

add databse.png

There are lots of templates and different databases available. Here we will be building a project database using the kanban board. Next time whenever you complete an ongoing project, move it to the "Completed" section, and you can see the change instantly on your website.

Go ahead and add some projects, dummy or actual, which you have already completed.

dummy.png

Making a new integration.

Now let's connect our database to a new integration. Go to the official page of Notion API and click on 'My Integrations' in the top-right corner.

Make a new integration.

integrations.png

Copy the Token ID somewhere safe, we'll be using it for authentication ahead.

Now let's connect our database to the newly created integration.

Simply, head over to the new page we created, click on Share, and search for the integration we just created.
Slide 16_9 - 1.png

Setting up the backend.

Now, we'll make our own API, which will fetch the data through Notion API and then filter through the data, to display what is actually relevant.

Go ahead and run npm init -y.

Make sure you have the latest NodeJS version installed.

We'll need three packages,

npm install express @notionhq/client dotenv
Enter fullscreen mode Exit fullscreen mode

Install nodemon, to keep the server active throughout the process.

npm install nodemon --save-dev
Enter fullscreen mode Exit fullscreen mode

Go over to the package.json file, and add a new script for nodemon.

"dev" : "nodemon index.js"
Enter fullscreen mode Exit fullscreen mode

Make a new .env file, and add the Token ID we created.

NOTION_TOKEN_ID=yourtokenid
Enter fullscreen mode Exit fullscreen mode

Head over to the index.js file, and initialize dotenv and require the Auth Client from the Notion SDK.

const dotenv = require('dotenv').config()
const { Client } = require('@notionhq/client')
Enter fullscreen mode Exit fullscreen mode

Now, we need to acquire the database ID to fetch data from the new page we created.

There are 2 ways to find this out, either you can use Postman (or any other API testers) and make a GET request to https://api.notion.com/v1/databases with the Bearer Token ( the Token ID).

postman.png
Or head over to the index.js file, create a new Client

const notion = new Client({
  auth: process.env.NOTION_TOKEN,
})
Enter fullscreen mode Exit fullscreen mode

Now, create an async function.

const listDatabases = async () => {
  const res = await notion.databases.list();
  console.log(res);
};

listDatabases();
Enter fullscreen mode Exit fullscreen mode

Now run npm run dev, and if you check the console, you'll be able to view the same result.

Head over to the .env file, and add this database ID

NOTION_DATABASE_ID=yourdatabaseid
Enter fullscreen mode Exit fullscreen mode

Now let's set up the express server,

const express = require('express');

const app = express( )

app.listen(process.env.PORT || 3000, console.log('Server is up and running!') )
Enter fullscreen mode Exit fullscreen mode

Fetching data from the database.

Now let's fetch the raw data we get from the Notion API.

Start with defining a constant payload, which we will pass through the request as follows

const getProjects = async ( ) => {
    const payload = {
        path: `databases/${database_id}/query`,
        method: 'POST'
    }
}
Enter fullscreen mode Exit fullscreen mode

The path is mentioned in the Notion API documentation, although we won't be needing the root URL, since we are using the SDK.
query-notion.png
Source: Notion API documentation

From the response, we just need the results object, hence destructure the object and try to log the response onto the console.

const database_id = process.env.NOTION_DATABASE_ID

const getProjects = async ( ) => {
     const payload = {
        path: `databases/${database_id}/query`,
        method: 'POST'
    };

  const { results } = await notion.request(payload);
return results;
}

const data = await getProjects( );
console.log(data);
Enter fullscreen mode Exit fullscreen mode

You should now be getting the list of cards, we made previously in JSON format as follows.
results-1.png

Modifying the API call.

As you have seen, the response has a lot of junk data. In this section, we'll filter through the data, and send a personalized object.

Now the objective is to get only the cards, that have the marked status "Completed".

Inside the getProjects function, let's map through the response, and return a customized object back.

const projects = results.map( page => {
    if ( page.properties.Status.select.name === 'Completed' ) {
        return {
        id: page.id,
        title: page.properties.Name.title[0].text.content,
        status: page.properties.Status.select.name,
      }
    }
} )
Enter fullscreen mode Exit fullscreen mode

Now, projects will be an array of objects each containing an object with the status 'Completed'.

It will also have some null values. We can remove these by using the filter function.

This can be implemented in the return statement as follows,

return projects.filter(project => project);
Enter fullscreen mode Exit fullscreen mode

Now, the final response should only contain an array of objects with the status 'Completed'.
results-final.png

What's left now is to set up a route in our express server.

app.get('/projects', async (req, res) => {
  const projects = await getProjects( )
  res.json(projects)
})
Enter fullscreen mode Exit fullscreen mode

Displaying the data on a NextJS project.

Our API is Ready!

The final task is to display it to a front-end. Go ahead and initialize a new NextJS project. (or if you have an existing project)

npx create-next-app notion-api
Enter fullscreen mode Exit fullscreen mode

Go to pages/index.js.
( or any other route you prefer, depending on the type of project your working on)

Make a new .env.local file to store the API URL. NextJS comes in-built with environment variables support.

NEXT_API=https://localhost:8000/projects
Enter fullscreen mode Exit fullscreen mode

In NextJS, to receive data from the endpoint, NextJS uses an async function called getStaticProps. By using this function, NextJS will pre-render the data on the server-side on build time, rather than fetching the data when the page first loads.

export async function getStaticProps( ) {
  // get posts from our api
  const res = await fetch(process.env.NEXT_API)
  const projects = await res.json()

  return {
    props: { projects },
  }
}
Enter fullscreen mode Exit fullscreen mode

We can now get hold of this array, by passing it to the default function.

export default function Home ({ projects }) {
    return (
        <ul>
            { 
                 projects && projects.map( (project, index) => <li key={project.id}>{project.title}</li>) 
             }
        </ul>
    )
}
Enter fullscreen mode Exit fullscreen mode

Congrats! You're doing a great job!

You can check what I did with Notion API on my portfolio page here.

Resources

I could build this through Traversy Media's video on Youtube, so if you get stuck, check out his tutorial!

Thanks for Reading!🎉

The Notion API can be tweaked in many ways. You can integrate it with Slack, Typeform, etc. It's a really powerful tool. As a personal advice, if you haven't worked with API's before, I think Notion API is just the place. It's really simple and has a great documentation with plenty of video tutorials online. Hit me up on Twitter with your creation!

If you need the source code, do let me know in the comments section below, I'll respond as soon as possible👍

Support me 🙌

My blogs are powered by coffees, if you feel I deserve one, Thanks❤

Discussion (2)

Collapse
taimoorsattar7 profile image
Taimoor Sattar

You don't need to create seperate express server. NextJS has it's own built API route support.

Collapse
geobrodas profile image
Georgey Author • Edited

Yeah @taimoorsattar7 , I'm new to NextJS, I realised it soon afterwards.
But since this is a beginner's tutorial, I wanted to include creating a server using express. And I feel Notion API is the best way to get started with API's

But seriously,NextJS is so special! Thanks for reminding!