A clean, fast Notion-powered personal blog built with Next.js 14 + TypeScript.
NotionP is a blog template using a Notion Database as the CMS. It includes:
- Post list with search & tag filtering
- Post detail page rendered via react-notion-x
- Global dark mode
- Image proxy to mitigate Notion expiring signed URLs
- Dynamic Open Graph image for social sharing previews
|
|
- Next.js 14 (Pages Router)
- React 18
- TypeScript
- Tailwind CSS
- react-notion-x / notion-client / notion-utils
- next-themes (dark mode)
npm installCreate a local env file:
cp .env.local.example .env.localFill in:
NOTION_SECRET_KEY=secret_xxxStart dev server:
npm run devDefault URL:
- http://localhost:3000 (if occupied, it will try 3001/3002...)
Site configuration lives in site.config.ts:
rootDatabaseId: Notion Database ID (post source)name/domain/author/descriptionnavigationLinks: top navigation
NotionP expects these properties (case-sensitive):
Name: titleAbstract: summary (optional)Tags: tags (Multi-select, optional)
It uses Notion created_time as the primary sorting key (newest first).
Required env vars:
NOTION_SECRET_KEY
- Fork this repo
- Create a Notion Integration and copy the Secret Key
https://www.notion.so/my-integrations - Add the Integration to your Notion Database page (Connections)
- Update
rootDatabaseIdin site.config.ts - Import the repo in Vercel and set
NOTION_SECRET_KEY
This is usually caused by stale dev assets or port switching. Try:
rm -rf .next
npm run devThen hard refresh the browser (Cmd+Shift+R).
Some Notion image URLs are signed and expire. This project uses /api/image as a proxy with caching to reduce broken images.
MIT

