Skip to content

Latest commit

 

History

History
145 lines (105 loc) · 7.7 KB

README.en.md

File metadata and controls

145 lines (105 loc) · 7.7 KB

Based on Next.js and Notion Public API, this blog system supports embedding MDX code in Notion to achieve more enriched effects.

简体中文

Features

  1. Built using Next.js, TS, Tailwind CSS, and other plugins (Shiki, React-pdf, and more).
  2. Uses Notion as the CMS, supporting embedding MDX code in Notion.
  3. Utilizes the Notion Public API, supporting cached data to improve overall performance.
  4. Supports dark mode and multi-language support.
  5. Supports Next SSG.
  6. SEO-friendly.
  7. Uses umami as the website analytics tool.
  8. Use supabase to manage user siginup/signin

Tech Stack

Frameworks

  1. Next.js
  2. Notion
  3. Tailwind CSS and shadcn
  4. Supabase

Components

  1. Shiki: Renders code blocks.
  2. React-pdf: Renders pdf blocks.
  3. iframely / unfurl: Renders bookmark, link-preview, and video blocks (Notion only returns URLs without Open Graph infos).
  4. Katex: Renders equation blocks.
  5. MDX: Renders mdx

Live Demo

✨ Getting Started

Prerequisites

  1. Duplicate this Notion template and edit your blog.
  2. Follow Notion's getting started guide to get a NOTION_TOKEN and a NOTION_DATABASE_ID.

Development and Deployment

  1. Set up: Star and Fork the repository.
  2. Install the dependencies:
npm install
  1. Set up your .env file with NOTION_TOKEN and NOTION_DATABASE_ID:
NOTION_TOKEN=
NOTION_DATABASE_ID=

# for supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
  1. Run locally:
# Locally
npm run dev

# Production
npm run build
npm run start

Open http://localhost:3000 in your browser to see the result.

About Notion

Choice of Solution

  1. Why choose Notion as the content editor? I have been using Notion for years, and previously, my blog workflow involved copying content from Notion to a Markdown editor like Hexo before publishing. This process was cumbersome and inefficient, as it required converting to Markdown format. By using Notion as the CMS, I can publish content directly, eliminating the need for frequent synchronization and edits.

  2. Why rebuild the wheel instead of using existing capabilities like react-notion-x? The main reason is that most implementations on Git are based on Notion's non-public API, which has the following drawbacks:

  • The non-public API requires publishing Notion data to the external web, compromising data privacy.
  • The non-public API relies on cookies, which may be deprecated or changed in the future, affecting stability.
  • When testing, the non-public API has issues with pulling content when the page size is too large. By contrast, the public API supports pagination, providing more reliable stability.

Although the public API lacks advanced features like Database View, its basic capabilities are sufficient for most use cases. Therefore, I chose to adopt the Notion Public API for this implementation.

Supported Blocks

Most common block types are supported. But some blocks information not supported in Public API, So we give an abbreviated rendering.

Block Type Supported Notes
Paragraph ✅ Yes
Headings ✅ Yes
Bookmark ✅ Yes Use unfurl.js
Bulleted List ✅ Yes
Callout ✅ Yes
Child Databases ✅ Yes Use tanstack/table
Child page ✅ Yes
Code ✅ Yes Use shiki
Column list and column ✅ Yes
Embed ✅ Yes
Equation ✅ Yes Use katex
File ✅ Yes
Image ✅ Yes No position、size info in API
Link Preview ✅ Yes Use unfurl.js
Mention ✅ Yes Only Date
Numbered List ✅ Yes
PDF ✅ Yes
Quote ✅ Yes
Synced block ✅ Yes
Table ✅ Yes
To do ✅ Yes
Toggle blocks ✅ Yes
Video ✅ Yes Use iframely
Breadcrumb ❌ Missing Not planned
Template ❌ Missing Not planned.
Divider ❌ Missing API Unsupported.
Table Of Contents ❌ Missing API Unsupported.

Why iframely?

  1. For block types such as image, video, bookmark, and link-preview, the Notion API only returns URLs without rendering the relevant data structures (e.g., title, description, icon, etc.). Therefore, an alternative solution is needed, and iframely is chosen for this purpose. Notion officially also uses iframely.

  2. Since iframely requires payment, unfurl.js is used as a fallback option, although there may be some differences in effectiveness.

Configuration

  1. Top Navigation
  2. Supported environment variables including NOTION_TOKEN, NOTION_DATABASE_ID, etc.
  • Set in the .env file for self-deployment or on the Vercel dashboard.
  • Enable MDX: RENDER_MDX=true and set the language to markdown in Notion's code block.
  • Enable Redis caching: REDIS_URL="redis://localhost:6379", otherwise, memory and file caching will be used.
  • Notion data expiration time: NEXT_DATACACHE_EXPIRE, defaulting to 1 hour. Note that if Notion is used to store files such as PDFs or images, the expiration time should not be too long to avoid expired file links.

Reference

  1. Notion Public API
  2. Next.js