Type-safe Notion contentlayer to easily build Notion-backed blogs, changelogs and more
Notion Contentlayer is a type-safe solution for easily fetching and rendering Notion content. Content is transformed to MDAST, so you can easily integrate with the Remark and Rehype ecosystem. Read more →
- Runtime & type-safe way to consume Notion page properties.
- Versatile renderer for MDAST content. Learn more →
- Integrates with Remark & Rehype ecosystem. Learn more →
- Install the Notion contentlayer package
$ npm install notion-contentlayer
- Setup a Notion database for your content
Hello World
How do I find my API key and table ID?
TODO: Write it up
- Create 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,
})
- Consume the content
All notion-contentlayer
functions have Rust-inspired error handling built-in, so you don't need to try
/ catch
anything. Just consume as below.
// 👇 `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 type { Root } from "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
}[]
*/
TODO Write Docs
Since notion-contentlayer
transforms all Notion blocks into a MDAST, you can perfectly integrate with the Remark and Rehype ecosystem.
Here's an example of how to use it to render HTML
const notionClient = new Client({
auth: process.env.NOTION_API_KEY,
})
const notionSource = createNotionSource({
// your options
})
const mdastResult = await notionSource.getPostContents('post-id-123')
if (mdastResult.isErr()) {
console.error(mdastResult.error)
return
}
const file = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(mdastResult.value)
console.log(String(file))
// => "<h1>Notion example</h1><h2>Autolink literals</h2> ..."
- Clone this repository
- Enable Corepack using
corepack enable
(usenpm i -g corepack
for Node.js < 16.10) - Install dependencies using
pnpm install
- Run the tests using
pnpm dev
Made with ❤️ in Helsinki, Finland.
Published under MIT License.