Notion: A Headless CMS without the Headache

AKA: How I built this site.

Mon Oct 02 2023

When you’re building an application that serves content to a user, a big consideration is your method of managing that content. Where will users create their content? How do they collaborate? How will you manage the permissions of what’s created? How will your presentation layer (ex: front end of a web application) access and serve said content? Most importantly, how will you do all of the above while respecting the authentication requirements of your process?

Born from this complexity come content management systems. These come in many flavors (ex: Wordpress), but developers seek solutions where content creation and management is decoupled from presentation. This subtype, called headless, provides developers with configurable methods of creating and managing content, along with programmatic ways of accessing those objects (ex: through an API) to a presentation layer of your choosing.

Headless CMS services like Contentful are promising plug and play solutions, but have a high lifetime cost for individuals & small orgs. The same can even be said about open source alternatives like Strapi. While you won’t pay for the application itself, you will pay for the node server that runs Strapi, the DB, and the content distribution network for your static assets (ex: images). These services also require you to learn their user interface to configure the rules of the CMS. That means valuable dev time wasted in documentation.

This is where Notion really shines. Notion is a familiar user interface, making creating content easy to learn for the user. This is extends to the dev as well, making the learning curve for configuration short and sweet. Most importantly, for the common use cases of the individual dev: it’s free.

Notion provides all this functionality through a well documented API. Through this API, authenticated applications can access all the content of databases in your workspace. This means that all the customizability of notion pages are yours to work with. Define your own fields easily, and organize pages by templates of your design. Or better yet, use any of the templates from the community!

This very blog uses Notion as a Headless CMS. Here’s a quick guide on how you can get Notion up and running for a blog of your own!

  1. Sign in on Notion and create a workspace.

  2. In your workspace, create a database. Make columns for fields of your content that you imagine using filters on when searching through all your content. Here’s a quick example of what fields you might see in a basic blog’s database:

    Screenshot_2023-07-12_at_11.19.17_PM.png

  3. Make an integration. Make sure to give it the right permission (ex: for a blog, I’d want my front end to have read permissions for my database objects).

  4. Save the Notion api key and database url as environment variables that are kept on the web server (you don’t want your users to have your key).

  5. Add capabilities to your web application for requesting data from your web server to the Notion API with the secrets you just saved. This can be through cURL or the Notion Javascript SDK. You want these requests to happen server side (since you’ll need the secrets on the server to access content from the workspace). If you have trouble through this part, don’t worry. Notion has rich documentation on the API. When doing this step, you’ll notice how easy it is to filter and sort content objects in your database. In essence, all the functionality of filtering and sorting in the Notion client is replicable in the API as a request.

  6. Access your desired fields from the JSON response object. A good JSON viewer will help you greatly when finding the paths to fields your interested in. Populate your components with the values you need, and present them to the viewer.

And you’re done! I know this is a high level overview, but the documentation on how to do this in any framework of choice already exists. Down the line, I hope to make a detailed guide on how to do this in Sveltekit + Svelte (which is how I made this site). Stay tuned for that.