# How I'm using Notion as a CMS for my personal Blog

If you like what I write, you can read this blog as well as the others on my official blog - [https://blog.atchyut.dev/blogpost/767de912c4c942509a7956d54ef0db7a](https://blog.atchyut.dev/blogpost/767de912c4c942509a7956d54ef0db7a)

I’ve been wanting to set up a blog for the longest time now. But, I’ve been quite busy with work and couldn’t take the time to build it. So finally it was time for Christmas and I managed to get some freedom to work on this as well as [my website](https://atchyut.dev/) and here’s how it went.

The website was pretty straightforward, I just built it using [Next.js](https://nextjs.org/), [TypeScript](https://www.typescriptlang.org/) (cause, of course TS), [Tailwind](https://tailwindcss.com/) (it’s such a blessing ❤️) and [Framer](https://www.framer.com/motion/) for some cool little animations. For the blog however, I needed a CMS because I of course didn’t want to go back and edit my code for every blogpost I end up creating, moreover, I was afraid I just wouldn’t write any posts because it would have been tedious without a CMS, so yes, CMS was a no brainer.

Also, I’m using a monorepo setup for my website and blog (and some other things that’ll come along soon), so that’s [PNPM](https://pnpm.io/) with [Turborepo](https://vercel.com/solutions/turborepo).

## **Why Notion?**

I use Notion everyday for all of my note taking and it just made sense for me to be able to add a simple Notion page and have my blog use that instead of having to manage a CMS to create and edit blogposts. I also want to mention that, Notion already allows users to just make their pages public for the world to see, but I just wanted it to be via my website, plus, I wanted to have my own styling so my portfolio and blog could look and feel the same.

## **Getting started**

Before I could have this wonderful blog, there were a few pieces of the puzzle that I had to gather.

* Firstly, an API to retrieve my notion pages, so in this case, I am using the [Notion JavaScript SDK](https://github.com/makenotion/notion-sdk-js), it’s pretty awesome, I’ve used it in the past too and would recommend it to anyone interested in a heartbeat.
    

* Secondly, I needed a backend to call the Notion APIs (via the SDK of course) because of CORS and for that, I’m using [Netlify’s Functions](https://docs.netlify.com/functions/overview/) along with their [CLI](https://docs.netlify.com/cli/get-started/).
    

**Trivia time**: did you know that the Netlify CLI makes it super easy (and barely an inconvenience - if you know you know) to inject your environment variables into your development environment via the netlify dev command?

* Lastly, I needed a way to convert the Notion blocks (i.e. their API response) to JSX. This, however, was a bit tricky, because I only found 2 npm packages that did it and they didn’t have all the flexibility that I needed for my usecase. So, that’s when I decided to build my own Notion to JSX parser.
    

Behold, [**notion-jsx**](https://github.com/theonly1me/notion-jsx) (here’s the [npm package](https://www.npmjs.com/package/notion-jsx)). A simple library that will convert your Notion page blocks to JSX. It currently supports most of the block types (this blog is a quick demonstration of its capabilities 😉), so whatever you’re seeing on this webpage is coming from my Notion page and then being parsed by **notion-jsx** to render these beautiful, beautiful components. And yes! Did I mention, ***it’s completely free and open source*** so, please feel free to step in and contribute in making it even better.

## **Diving into the code**

![](https://media2.giphy.com/media/3o6Ztroynp3WpqLD1u/giphy.gif?cid=7941fdc6d65vbrk0v9jwobksdrbe33fnqo01th2hw44i7qak&ep=v1_gifs_search&rid=giphy.gif&ct=g align="center")

Before we hop in though, if you stuck with me so far, thank you! I really appreciate you reading my very first blogpost (on my blog, at least) and hope you’ll keep reading more of my blogs as I keep posting them. I know, we’re missing a mailing list 🥲, but more on that soon. Okay, now let me show you how easy it is to have your own blog that is powered by Notion.

First, you’ll need a super simple React app (can be a meta framework like Next.js, Preact, Remix or anything that uses JSX and React under the hood). You’ll also need some kind of a backend, so you can either go serverless like Netlify Functions, Firebase Cloud Functions, Cloudflare workers or simply use NextJS / Remix since they will allow you to have server side logic practically inside (not literally) your React app, and that’ll help you bypass CORS troubles. Then, you can install the Notion JavaScript SDK. If you want to use the APIs instead of the SDK, you can check out the [Notion API’s Workspace on Postman](https://www.postman.com/notionhq/workspace/notion-s-api-workspace/collection/15568543-d990f9b7-98d3-47d3-9131-4866ab9c6df2).

```javascript
 npm install @notionhq/client
```

In the meantime, on Notion’s Developer API website, you’ll need to set up an integration that will allow your app / server to fetch the Notion pages. You can follow the guide [here](https://developers.notion.com/docs/create-a-notion-integration) to do that easily. Now let’s actually step into Notion and set up a little database that can hold some important stuff for us. Let’s add the following columns to this table.

* name - the name of your blogpost
    

* tags - if you want to add some tags to associate with the blog. In my case, I use them to decide which notion pages to show on this website.
    

* imageUrl - for the cover image or card image etc.
    

* summary - if you want to show additional summary
    

* pageId - this is the most important part since it is going to allow you to fetch your page via the API. You can find the pageId at the end of your Notion Page’s link, it is a 32 character long alpha-numeric string.
    

After creating the table, fill in the first row with relevant information about your blogpost. Once you’re done with all that, just grant the integration you created access to this Notion database like shown [here](https://developers.notion.com/docs/create-a-notion-integration#give-your-integration-page-permissions). Alright, now you’re all set to jump back into the get the ball rolling.

### **Retrieving the blogs metadata**

First, you’ll need to initialize the Notion client, you can do that by using your integration secret (the one you would’ve created during the last step)

```typescript
 const notion = new Client({
  auth: NOTION_KEY as string, // NOTION_KEY is your integration secret
});
```

You can use the notion.databases.query function to retrieve the metadata from the database you just created. From the API response, de-structure the results array and take out the properties you’ll need to display on your blog or use to retrieve the individual pages (blogs).

```typescript
ttype ype// sorry about the lack of syntax highlighting, will add support for that soon!

const { results }: QueryDatabaseResponse = await notion.databases.query({
		// database_id can be found at the end of your database's link
    database_id: "660de912c4c942509a7956d54ea0dr13", 
    filter: { // filter by a status column or tags if you went with that
      property: 'tags',
      status: {
        equals: 'Live',
      },
    },
  });
```

If you’ve used a table like mine, you’ll end up with data that has the following properties:

```javascript
 export type Page = {
  pageId: string;
  pageName: string;
  imageUrl: string;
  pageSummary: string;
};
```

Now, before we start fetching the page, we need to understand that each Notion page is made up of multiple blocks, and therefore, to fetch an individual page, you’ll need to use the [Retrieve block children](https://developers.notion.com/reference/get-block-children) API to fetch all the blocks of that page where the block id, will be your page’s id. In code, it’ll be something like this.

```javascript
 const { results } = await notion.blocks.children.list({
    block_id: pageId as string,
  });
```

Now, once you have the results (blocks) from a page comes the fun part, [NotionJSX](https://github.com/theonly1me/notion-jsx). So, you can now take all of these blocks and convert them to JSX with the blink of an eye and snap of a finger.

![](https://images.unsplash.com/photo-1530084116302-2fa56616cdd6?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb align="left")

Using NotionJSX is super easy and in code, it will look like this.

```javascript
 import notionJSX from 'notion-jsx';

const elements =  notionJSX.generateJSX(blocks) as ReactElements[]

return (
	<div>
		{elements?.map((element: ReactElement, index: number) => {
        return React.createElement(
          element.type,
          {
            key: element.key || index,
            className: element.props.className,
            ...element.props,
          },
          element.props.children
        );
      })}
	</div>
);
```

And **BOOM**! Congratulations, your very own blog is ready and you’re using Notion as a CMS for it. With that being said, I’ll wrap this very first blogpost up, looking forward to seeing your blog if you end up creating one like me. Have a good one.
