How I built a Notion-powered blog on my Next.js portfolio; setup, rendering, and the bugs I ran into along the way.
Title — TitleSlug — TextDescription — TextDate — DatePublished — CheckboxTags — Multi-select.env.local:NOTION_API_KEY=your_key_here NOTION_BLOG_DATABASE_ID=your_database_id_here
npm install @notionhq/client@2.2.15
Pin to v2 — v3 restructured the API and breaks things.
import { Client } from '@notionhq/client'; const notion = new Client({ auth: process.env.NOTION_API_KEY }); export async function getBlogPosts() { const response = await notion.databases.query({ database_id: process.env.NOTION_BLOG_DATABASE_ID!, filter: { property: 'Published', checkbox: { equals: true } }, sorts: [{ property: 'Date', direction: 'descending' }], }); return response.results.map((page) => { // map properties to a clean BlogPost type }); }
react-notion-x:npm install react-notion-x notion-client prismjs
react-notion-x uses createContext, it must run on the client:'use client'; import { NotionRenderer } from 'react-notion-x'; import dynamic from 'next/dynamic'; const Code = dynamic(() => import('react-notion-x/build/third-party/code').then((m) => m.Code) ); export default function NotionContent({ recordMap }) { return ( <NotionRenderer recordMap={recordMap} fullPage={false} darkMode={true} disableHeader={true} components={{ Collection: () => null, Code }} /> ); }
Important:notion-clientuses the unofficial Notion API, so your pages must be set to public in Notion's share settings.
Module not found errors.Activities and Contact but my imports used activities and contact.git mv src/components/Activities src/components/activities_temp git commit -m "chore(): temp rename" git mv src/components/activities_temp src/components/activities git commit -m "fix(): lowercase folder names for Linux" git push origin main
.env.local. Go to Settings → Environment Variables and add NOTION_API_KEY and NOTION_BLOG_DATABASE_ID manually.404: NOT_FOUND on every page despite successful builds. Changing it to Next.js fixed it instantly.revalidate = 60. Code blocks, callouts, toggles — everything renders exactly as it looks in Notion.