Skip to content

Commit

Permalink
feat: add reame.zh-cn
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-guoba committed Mar 7, 2024
1 parent 1e249ee commit 9933656
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 59 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ next-env.d.ts

/scripts/load-testing/output.bin
Heap.*.heapsnapshot
README.en.md
160 changes: 102 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,93 @@

<p align="center">
<img alt="Example Page" src="https://github.com/alex-guoba/next-blogger/assets/2872637/5d23c303-6031-47aa-beec-7aad56357337" width="689">
<img alt="Example Page" src="https://github.com/alex-guoba/next-blogger/blob/main/assets/2872637/5d23c303-6031-47aa-beec-7aad56357337.png?raw=true" width="689">
</p>

Blog build on [Next.js](https://nextjs.org/) and [Notion Public API](https://www.notion.so/).
Blog built on [Next.js](https://nextjs.org/) and [Notion Public API](https://www.notion.so/).

## Features
[简体中文](./README.zh-CN.md)

## Features

1. Built using Next.js, TS, Tailwind CSS and other plugins(Shiki、React-pdf and others).
2. Use [Notion Public API](https://developers.notion.com/)
3. 支持使用 Prisma 缓存Notion数据,减少API访问,提升整体性能。
4. 支持深色模式。
5. 支持 [Static Site Generation](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation)
1. Built using Next.js, TS, Tailwind CSS, and other plugins (Shiki, React-pdf, and more).
2. Utilizes the [Notion Public API](https://developers.notion.com/).
3. Supports caching Notion data using Prisma to reduce API calls and improve overall performance.
4. Includes a dark mode option.
5. Supports [Static Site Generation](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation).
6. Includes load testing scripts, see [load-testing](./scripts/load-testing/).

## Tech Stack

### Frameworks

1. [Next.js](https://nextjs.org/)
1. [Next.js](https://nextjs.org/)
2. [Notion](https://www.notion.so/)
3. [Tailwind CSS ](https://tailwindcss.com/) and [shadcn](https://ui.shadcn.com/)
4. [Prisma](https://www.prisma.io/) : 缓存Notion数据,过期时间可配置。
3. [Tailwind CSS](https://tailwindcss.com/) and [shadcn](https://ui.shadcn.com/)
4. [Prisma](https://www.prisma.io/)

### Components

### Component
1. [Shiki](https://shiki.style/): render `code` blocks
2. [React-pdf](https://react-pdf.org/): render `pdf` blocks
3. [iframely](https://iframely.com/) / [unfurl](https://github.com/jacktuck/unfurl): render `bookmark``link-preview` and `video` blocks(Notion only return url without Open Graph infos)
4. [Katex](https://katex.org/): render `equation` blocks
1. [Shiki](https://shiki.style/): Renders `code` blocks.
2. [React-pdf](https://react-pdf.org/): Renders `pdf` blocks.
3. [iframely](https://iframely.com/) / [unfurl](https://github.com/jacktuck/unfurl): Renders `bookmark`, `link-preview`, and `video` blocks (Notion only returns URLs without Open Graph infos).
4. [Katex](https://katex.org/): Renders `equation` blocks.

### Platforms

(To be added)

## ✨ Getting Started

### Prerequisites

1. Duplicate [this Notion template](https://gelco.notion.site/910de43a0db24ebc9a34209ffab613a7?v=7f2614c5918f4a5bab3a6637b12a19f9&pvs=4), and edit your blog.
2. Follow Notions [getting started guide](https://developers.notion.com/docs/getting-started) to get a `NOTION_TOKEN` and a `NOTION_DATABASE_ID`.
1. Duplicate [this Notion template](https://gelco.notion.site/910de43a0db24ebc9a34209ffab613a7?v=7f2614c5918f4a5bab3a6637b12a19f9&pvs=4) and edit your blog.
2. Follow Notion's [getting started guide](https://developers.notion.com/docs/getting-started) to get a `NOTION_TOKEN` and a `NOTION_DATABASE_ID`.

### Development
1. Setup: Star and Fork the repository
2. install the dependences:

1. Set up: Star and Fork the repository.
2. Install the dependencies:

```bash
npm install
```
3. Set up you `env.local` with `NOTION_TOKEN` and `NOTION_DATABASE_ID`.
```

3. Set up your `.env` file with `NOTION_TOKEN` and `NOTION_DATABASE_ID`:

```ini
NOTION_TOKEN=
NOTION_DATABASE_ID=
```
4. run locally
4. (Optional) For performance considerations, it is recommended to configure database caching. See the Prisma documentation for various database [Connection URLs](https://www.prisma.io/docs/orm/reference/connection-urls). The default in the code is [Mysql](/prisma/schema.prisma):

```prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
```

```ini
DATABASE_URL="mysql://xxx:yyy@host:3306/dbname"
```

The first time you run it, you need to create the relevant table structure.

```shell
npm run db:init
```

5. Run locally:

```bash
# Locally
npm run dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
# Production
npm run build
npm run start
```

Open [http://localhost:3000](http://localhost:3000) in your browser to see the result.

## Supported Blocks

Expand Down Expand Up @@ -92,55 +123,68 @@ Most common block types are supported. But some blocks information not supported
| Divider | ❌ Missing | API Unsupported. |
| Table Of Contents | ❌ Missing | API Unsupported. |


## Performance

1. [dynamic](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic) route
1. [Dynamic Routes](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic)

关闭 `dynamic route` 可以减少重复渲染,大幅提升性能。下面为是否开启的性能对比:
Disabling `dynamic routes` can reduce redundant rendering and significantly improve performance. Below is a performance comparison between enabling and disabling this feature:

- `force-dynamic` :
- `force-dynamic`:

| Bucket | # | % | Histogram |
| Bucket | # | %!|(MISSING) Histogram |
|-----------------|------|--------|---------------------------------------------------------------------|
| [0s, 10ms] | 0 | 0.00% | |
| [10ms, 40ms] | 1 | 0.01% | |
| [40ms, 80ms] | 0 | 0.00% | |
| [80ms, 200ms] | 1 | 0.01% | |
| [200ms, 500ms] | 906 | 10.30% | ####### |
| [500ms, 1s] | 7885 | 89.67% | ################################################################### |
| [1s, +Inf] | 0 | 0.00% | |
| [0s, 10ms] | 0 | 0.00%!|(MISSING) |
| [10ms, 40ms] | 1 | 0.01%!|(MISSING) |
| [40ms, 80ms] | 0 | 0.00%!|(MISSING) |
| [80ms, 200ms] | 1 | 0.01%!|(MISSING) |
| [200ms, 500ms] | 906 | 10.30%!|(MISSING) ####### |
| [500ms, 1s] | 7885 | 89.67%!|(MISSING) ################################################################### |
| [1s, +Inf] | 0 | 0.00%!|(MISSING) |

- `auto` (default):

| Bucket | # | % Histogram | |
|-----------------|------|-------------------|--------------------------------------------------------------|
| [0s, 10ms] | 0 | 0.00% | |
| [10ms, 40ms] | 7727 | 80.49% | ############################################################ |
| [40ms, 80ms] | 1816 | 18.92% | ############## |
| [80ms, 200ms] | 54 | 0.56% | |
| [200ms, 500ms] | 3 | 0.03% | |
| [500ms, 1s] | 0 | 0.00% | |
| [1s, +Inf] | 0 | 0.00% | |
| Bucket | # | %!|(MISSING) Histogram |
|-----------------|------|--------|------------------------------------------------------------------|
| [0s, 10ms] | 0 | 0.00%!|(MISSING) |
| [10ms, 40ms] | 7727 | 80.49%!|(MISSING) ############################################################ |
| [40ms, 80ms] | 1816 | 18.92%!|(MISSING) ############## |
| [80ms, 200ms] | 54 | 0.56%!|(MISSING) |
| [200ms, 500ms] | 3 | 0.03%!|(MISSING) |
| [500ms, 1s] | 0 | 0.00%!|(MISSING) |
| [1s, +Inf] | 0 | 0.00%!|(MISSING) |

## Learn More

### Why Notion?

## Learn More
1. Why choose Notion as the content editor?
I have been using Notion for many years. In the past, when creating blogs, I would write content in Notion, copy it to editors like Markdown, and then publish it using hexo. This process was cumbersome and required converting the format to Markdown, which was inconvenient. By using Notion as a CMS, I can directly publish content written in Notion without the need for frequent synchronization after making changes.

2. Why reinvent the wheel instead of using existing solutions like `react-notion-x`?
The main reason is that most implementations on GitHub are based on Notion's unofficial API, which has several drawbacks:
- The unofficial API does not have official documentation, so one has to figure out the data structure on their own.
- The unofficial API requires publishing Notion data to the internet, which may compromise data privacy.
- The unofficial API may be deprecated or changed in the future, making it unstable.
- During testing, I found that the unofficial API sometimes fails to fetch large pages. In contrast, the public API supports pagination and is more stable.
In summary, while the Public API lacks some advanced features like Database View support, it meets the basic requirements. Therefore, I chose to implement it using the Notion Public API.

3. Why Use `Prisma` to Cache Notion Data

1. 为何选用Notion作为内容编辑器?
本人已有多年使用Notion的习惯,以前博客的做法是将用Notion写好后再copy到Markdown等编辑器,使用hexo发布。这样流程会非常长,而且需要适配markdown格式,非常的不方便。所以直接使用Notion作为CMS,写好的内容可以直接发布。
The Notion API has frequency limitations, and for some deeply nested pages, multiple accesses can easily exceed these limitations. Additionally, API access can be unstable in certain regions, significantly impacting page performance. To address these issues, caching is used. Furthermore, some data returned by the Notion API, such as image URLs, have a limited validity period, necessitating cache invalidation. By default, the cache expires after one hour. For more details on expiration strategies, refer to the official documentation on [notion-hosted-files](https://developers.notion.com/reference/file-object#notion-hosted-files).

2. 为何要重造轮子,而不是直接使用`react-notion-x`等已有的能力实现渲染。
原因有几点:
- Git上大部分的类似产品都使用非公开的Notion API,在官网上没有相关文档,只能自己摸索其数据结构。
- 非公开的API要求将Notion数据公开到外网,无法保障数据隐私。
- 非公开的API存在后续可能废弃、变更的隐患。
虽然Public API在能力上有所缺失,比如不支持 Database View 等能力,但是常规的能力基本都可以满足。所以选择采用Notion Public API实现。
`Prisma` is chosen as the caching component due to its flexibility and support for various databases, including MySQL, MongoDB, and others. For more information, refer to the official [Doc](https://www.prisma.io/docs/orm/overview/databases).

3. 为何要采用`Prisma`缓存Notion数据
Notion的API存在频率限制,一些嵌套层次比较深的Page多次访问是很容易超过API的频率限制。而且部分地区API访问不稳定,对页面性能影响较大,所以使用缓存来解决。
另外Notion API返回的部分数据(比如图片url)存在有效期,所以也需要考虑过期时间。详见[notion-hosted-files](https://developers.notion.com/reference/file-object#notion-hosted-files)
### 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](https://www.notion.so/help/embed-and-connect-other-apps#embeds-in-notion).

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

## TODO

- [ ] Deploy on Vercel

## Reference

1. [Notion Public API](https://developers.notion.com/reference/intro)
Loading

0 comments on commit 9933656

Please sign in to comment.