Skip to content

Commit

Permalink
feat: add sharebar, remove prisma cache
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-guoba committed Apr 3, 2024
1 parent 884bd3a commit 591a6ac
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 511 deletions.
32 changes: 3 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<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">
<img alt="Example Page" src="https://github.com/alex-guoba/next-blogger/assets/2872637/b05f04b0-3d05-4ab3-8a8e-be2093a349c5" width="689">
</p>

Next-Blogger built on [Next.js 14+](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/), use [Notion](https://www.notion.so]) to manage your content.
Expand All @@ -10,7 +10,7 @@ Next-Blogger built on [Next.js 14+](https://nextjs.org/) and [Tailwind CSS](http

1. Built using Next.js(14+ with App Router ), Typescript, 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.
3. Supports caching Notion data using `unstable_cache` to reduce API calls and improve overall performance.
4. Includes a dark mode option.
5. SEO friendly with RSS feed, sitemaps and more!
6. Includes load testing scripts, see [load-testing](./scripts/load-testing/).
Expand All @@ -24,7 +24,6 @@ Next-Blogger built on [Next.js 14+](https://nextjs.org/) and [Tailwind CSS](http
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/)

### Components

Expand Down Expand Up @@ -59,26 +58,8 @@ npm install
NOTION_TOKEN=
NOTION_DATABASE_ID=
```
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 [postgresql](/prisma/schema.prisma):

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

```ini
DATABASE_URL="postgres://xxxx"
```

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

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

5. Run locally:
4. Run locally:

```bash
# Locally
Expand Down Expand Up @@ -176,20 +157,13 @@ The main reason is that most implementations on GitHub are based on Notion's uno
- 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

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).

`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).

### 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


## Reference

Expand Down
36 changes: 4 additions & 32 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

<p align="center">
<img alt="示例页面" src="https://github.com/alex-guoba/next-blogger/assets/2872637/5d23c303-6031-47aa-beec-7aad56357337" width="689">
<img alt="示例页面" src="https://github.com/alex-guoba/next-blogger/assets/2872637/b05f04b0-3d05-4ab3-8a8e-be2093a349c5" width="689">
</p>

基于[Next.js](https://nextjs.org/)[Notion Public API](https://www.notion.so/)构建的博客模板。
Expand All @@ -9,11 +9,12 @@

1. 使用Next.js、TS、TailwindCSS构建。
2. 使用Notion作为CMS。
3. 使用Notion Public API,同时支持使用Prisma缓存数据,减少API访问,提升整体性能。
3. 使用Notion Public API,同时支持使用 `unstable_cache` 缓存数据,减少API访问,提升整体性能。
4. 支持深色模式。
5. 支持[Next静态网站生成](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation)
6. 支持压力测试,详见[load-testing](./scripts/load-testing/)
7. SEO友好
8. 使用[umami](https://umami.is/)作为站点统计工具。

## 技术栈

Expand All @@ -22,7 +23,6 @@
1. [Next.js](https://nextjs.org/)
2. [Notion](https://www.notion.so/)
3. [Tailwind CSS](https://tailwindcss.com/)[shadcn](https://ui.shadcn.com/)
4. [Prisma](https://www.prisma.io/)

### 组件

Expand Down Expand Up @@ -56,27 +56,7 @@ npm install
NOTION_TOKEN=
NOTION_DATABASE_ID=
```

4. [可选]考虑性能,建议配置数据库缓存,详见`prisma`文档中各种数据库的[连接URL](https://www.prisma.io/docs/orm/reference/connection-urls)配置。代码中默认使用[Mysql](/prisma/schema.prisma)

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

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

首次运行时需要创建相关表结构。

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

5. 本地运行
4. 本地运行

```bash
# 本地开发
Expand Down Expand Up @@ -171,20 +151,12 @@ npm run start
- 非公开的API在测试时发现page内容过大时会存在拉取失败的情况。而公共API支持分页,稳定性更可靠。
总之,虽然Public API在高级特性上有所缺失,比如不支持 Database View 等能力,但是基本能力已经可以满足需求。故最终选择采用Notion Public API实现。

3. 为何要采用`Prisma`缓存Notion数据
Notion的API存在频率限制,一些嵌套层次比较深的Page多次访问是很容易超过API的频率限制。而且部分地区API访问不稳定,对页面性能影响较大,所以使用缓存来解决。另外Notion API返回的部分数据(比如图片url)存在有效期,所以也需要考虑缓存失效,默认1个小时过期。过期策略详见官方文档[notion-hosted-files](https://developers.notion.com/reference/file-object#notion-hosted-files)
使用 `Prisma` 作为缓存组件是因为其灵活性,支持各类数据库,包括Mysql、MongoDB等,详见官方[Doc](https://www.prisma.io/docs/orm/overview/databases)

### Why iframely?

1. `image`, `video`, `bookmark` 以及 `link-preview`等类型的block,Notion API仅返回URL,没有渲染相关数据结构(如title、desciprtion、icon等)。所以需要自己寻求解决方案,此处选择了iframely作为替代。Notion官方也是采用[iframely](https://www.notion.so/help/embed-and-connect-other-apps#embeds-in-notion)

2. iframely需要付费,所以也采用了unfurl.js作为兜底,效果上会有差距。


## TODO
- [ ] Deploy on Vercel


## Reference
1. [Notion Public API](https://developers.notion.com/reference/intro)
6 changes: 5 additions & 1 deletion app/(blog)/article/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { NotionApiCache } from "@/app/notion/cache";
import { ArticlePost, dbQueryParams } from "@/app/notion/fitler";
import { getTableOfContents } from "@/app/notion/toc";
import { DashboardTableOfContents } from "@/components/layouts/toc";
import { ShareBar } from "@/components/share-bar";

// https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = env.REVALIDATE_PAGES; // revalidate the data interval
Expand Down Expand Up @@ -92,6 +93,8 @@ export default async function Page({ params }: { params: { slug: string[] } }) {
if (!blocks) {
return <div />;
}
const url = siteMeta.siteUrl + "/" + params.slug.join("/");

const toc = getTableOfContents(blocks);
const has_toc = toc.items.length > 0;

Expand All @@ -104,7 +107,6 @@ export default async function Page({ params }: { params: { slug: string[] } }) {
{formatDate(lastEditTime)}
</PageHeaderDescription>
</PageHeader>
{/* <Separator className="mb-2.5" /> */}

<React.Suspense fallback={<ContentLoadingSkeleton></ContentLoadingSkeleton>}>
<section className="mt-8 flex w-full flex-col gap-y-0.5">
Expand All @@ -114,6 +116,8 @@ export default async function Page({ params }: { params: { slug: string[] } }) {
</section>
</React.Suspense>

<ShareBar url={url} title={title} image={siteMeta.siteUrl + siteMeta.socialBanner}></ShareBar>

<Link href="/" className={cn(buttonVariants({ variant: "ghost", className: "mx-auto mt-4 w-fit" }))}>
<ChevronLeftIcon className="mr-2 h-4 w-4" aria-hidden="true" />
See all posts
Expand Down
9 changes: 5 additions & 4 deletions app/notion/_components/db/base-column.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Checkbox } from "@/components/ui/checkbox";
import { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "@/components/ui/data-table/column-header";
import { formatDate } from "@/lib/utils";
// import { DataTableColumnHeader } from "@/components/ui/data-table/column-header";
// import { formatDate } from "@/lib/utils";

export type NotionRowProps = {
id: string;
Expand Down Expand Up @@ -35,7 +35,7 @@ export function BaseColumn(): ColumnDef<NotionRowProps>[] {
enableSorting: false,
enableHiding: false,
},
{
/*{
accessorKey: "id",
header: ({ column }) => <DataTableColumnHeader column={column} title="ID" />,
enableSorting: false,
Expand Down Expand Up @@ -87,7 +87,8 @@ export function BaseColumn(): ColumnDef<NotionRowProps>[] {
/>
);
},
},
},*/

// {
// accessorKey: "url",
// header: ({ column }) => <DataTableColumnHeader column={column} title="URL" />,
Expand Down
6 changes: 0 additions & 6 deletions app/notion/proxy/prisma.ts

This file was deleted.

Loading

0 comments on commit 591a6ac

Please sign in to comment.