How to use Notion API with NextJS?

How to use Notion API with NextJS?

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

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

npm install nodemon --save-dev

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

"dev" : "nodemon index.js"

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

NOTION_TOKEN_ID=yourtokenid

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')

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 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,
})

Now, create an async function.

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

listDatabases();

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

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!') )

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'
    }
}

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);

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,
      }
    }
} )

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);

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)
})

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

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

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 },
  }
}

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>
    )
}

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!

Lee Robinson had also live-streamed recently on Notion API.

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 personal advice, if you haven't worked with APIs before, I think Notion API is just the place. It's really simple and has 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 down below, I'll respond as soon as possible👍

Support me 🙌

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