02May 25, 2021

How this blog works: Notion API

The Notion API was recently released into the wild as a public beta, something that I have been waiting years for, since I started using Notion in 2018. It's very exciting, even in its baby state, and this blog that you're reading now actually uses the Notion API.

If you've never used Notion before, I encourage you to take a look over at notion.so, it's an incredible note-taking, life-organising, and work-simplifying app.

How it's set up

I have a Blog database set up in my workspace, which I've invited my integration to. This allows me to programatically access this database using the token I was issued when creating my integration.

Of course, since this blog is loaded in with client-side javascript, I had to find a way of hiding the secret token, as it also allows anyone with it to edit pages and content. I went with Google Cloud Functions. Using just a bit of code, and Notion's javascript sdk @notionhq/client, it's pretty easy to fetch a list of all the blog posts.

1const { Client } = require('@notionhq/client');
2const notion = new Client({ auth: process.env.NOTION_API_KEY });
3const today = new Date();
5exports.retrievePosts = async (req, res) => {
6  const posts = await notion.databases.query({
7    database_id: process.env.DATABASE_ID,
8    filter: {
9      property: 'Published',
10      'date': {
11        'on_or_before': today.toISOString(),
12      },
13    },
14    sorts: [
15      {
16        property: 'Published',
17        direction: 'descending',
18      },
19    ],
20  });
22  res.set('Content-Type', 'application/json');
23  res.send(posts);

The code sorts the blog posts by most recently published, and makes sure that posts with a published date in the future are not retrieved.

This cloud function just takes the JSON output of the Notion API call and returns it, ready to be used by my website. All I have to do is fetch the json from the cloud function url.

Retrieving the content of a blog post is similar, but when I fetch it on the client side, it has to be parsed into HTML. Currently, the API doesn't support loading images or other complex blocks, but it's sufficient for a simple text blog.

Source code

If you want to see exactly how I got it working, you can take a look at the repository on Github for my personal site here: https://github.com/GRA0007/portfolio

Last edited June 1, 2023