Guides
Notion Contentlayer: Making Notion a Practical Content Source for Your WEB App
RG
Rikard Wikström • Nov 8, 2024
Learn how Notion Contentlayer turns Notion into a structured, type-safe content source for blogs, documentation, and notes.
TLDR;
Notion Contentlayer makes it easy to use Notion as a type-safe, structured content source for blogs, documentation, and notes. It pulls content directly from Notion databases, keeping everything organised and up-to-date with minimal setup—ideal for developers looking to seamlessly integrate Notion into their applications.
We use Notion to manage everything from project notes to documentation, and we wanted a way to bring that content directly into our apps without complex setups. Notion Contentlayer does exactly that. It transforms Notion databases into structured, type-safe data that’s easy to work with, keeping content organised and current without constant backend tweaks. Now, Notion can be a powerful, developer-friendly content source.
Why Notion Contentlayer?
Notion Contentlayer bridges the gap between Notion’s flexibility and the structured needs of content-driven applications. It converts Notion data into a format compatible with MDAST, making Notion a structured, type-safe data source that integrates easily into any project. Ideal for anyone who wants to use Notion for blogs, documentation, or internal notes with minimal configuration.
Core Features
Type-Safe Content: Notion Contentlayer makes content from Notion databases type-safe, so it’s easy to handle in your code.
MDAST Compatibility: Converts Notion blocks into MDAST format, making it easy to integrate with tools like Remark and Rehype for custom rendering.
Built-In Error Handling: Inspired by Rust’s error-handling style, Notion Contentlayer provides clear error states to keep your app predictable and manageable.
Quickstart
Getting started with Notion Contentlayer is simple:
1. Install Notion Contentlayer:
$ npm install notion-contentlayer
2. Configure Your Notion Database: Add your Notion API key and database ID to your environment file.
.env file
# -----------------------------------------------------------------------------
# Blog (Notion)
# -----------------------------------------------------------------------------
NOTION_API_KEY="secret_..."
NOTION_TABLE_ID="..."
3. Define the Notion Source:
import { createNotionSource, url, people, checkbox, text, date, select, status, title } from "notion-contentlayer"
import { Client } from "@notionhq/client"
const notionClient = new Client({
auth: process.env.NOTION_API_KEY,
})
const notionSource = createNotionSource({
properties: {
cover: url("Image"),
authors: people("Authors"),
isFeatured: checkbox("Featured"),
slug: text("Slug"),
publishedDate: date("Date"),
isPublished: checkbox("Published"),
description: text("Description"),
category: select("Category"),
status: status("Status"),
featuredCover: text("FeaturedImage"),
title: title("Page"),
},
client: notionClient,
databaseId: process.env.NOTION_TABLE_ID as string,
})
4. Fetch and Use Content:
// 👇 `content`: true fetches the content for each blog post
const postResult = await notionSource.fetchPosts({ content: true })
// ^^^^^^^^^^ postResult is a `Result`
if (postResult.isErr()) {
// Render error state
console.error(postResult.error)
return
}
const posts = postResult.value;
/*
import { Root } from "@types/mdast"
`posts` is of type:
type Posts = {
cover: string
authors: User[]
isFeatured: boolean
slug: string
publishedDate: Date
isPublished: boolean
category: string
status: string
featuredCover: string
title: string
blocks: Root
}[]
*/