Notion博客常见解决方案
May 2, 2024
很多人习惯了用Notion来记录every thing,包括我自己。所以在博客方案的选型上也就会考虑围绕Notion来构建解决方案。Notion相对markdown、mdx等,在能力和数据结构上会复杂很多(参考notion的block类型),所以很少见到非常完美适配所有Notion能力的解决方案。个人在方案选型上使用了基于Notion的public API来开发,本文主要是介绍在开发过程中了解到的一些开源解决方案,大部分来自github。供考虑使用Notion搭建个人博客的同学参考。
难点
使用Notion作为CMS来实现博客,本质上是将Notion的数据内容、样式转化为web页面,在实现上有以下两个难点:
- Notion的内容组织方式灵活
Notion提供了Page(页面)、Database(数据库)、Block(内容)等几种组织方式。Page包括了其基本信息外,内容由一系列的blocks组成。Database除了其基础字段和用户自定义字段外,其内容又可以包括多个Page。Page之间也允许有嵌套关系,相当灵活。
- 各种Block类型
Notion提供了不下20中的block类型,即包括文本、head1-3、callout、quote、list等基础类型外,也包括column、pdf、file、bookmark等复杂数据类型。这里的复杂性主要体现在两个方面。
- 高级block类型的渲染
已bookmark为例,Notion用户只需要在文本里面贴上一个github链接,Notion要将页面的title、图片、logo、介绍等提取出来,渲染到页面上。包括embed还需要提取github单的状态。这可比markdown渲染一条漂亮的引用要复杂得多。再比如pdf,需要在页面上可以直接浏览,这种需要引入第三方lib来解决。
- 嵌套block
类型之间有各种嵌套关系。比如下面就是一个list lock嵌套list block的复杂场景(8层嵌套)。实际上大部分block类型都支持相互嵌套,比如在column里面嵌套list,在list里面再嵌套block。
零成本方案
Notion本身提供了页面发布的能力。即直接将需要发布的页面Publish到公网,外部就可以通过链接访问页面内容。这个方案比较简单,熟悉Notion的同学应该都知道了,这里就不再详细介绍。可以参考此文。
基于Notion API的解决方案
Notion提供了数据相关的接口API,可以将Notion中的内容(Page页面、Database数据库、Block页面内容等)以API的方式读取出来,供开发者自行渲染为想要的样式和组织方式。具体的页面组织方式和渲染样式比较多,但从依赖的API类型上看大体上可以分为以下两类。
私有API
即非官方API,私有API是我个人的叫法,意思是Notion没有正式提供给外部开发者使用的API,通常用于Noton自己的客户端使用。但是开发者可以通过页面抓包等方式抓取到链接后使用。此类方案以reaction-notion-x 为代表,基于此lib有着大量的扩展解决方案。
react-notion-x提供了以下能力:
- 读取了读取私有API的SDK notion-client
- react-notion-x 渲染各种notion的数据结构,包括基础block格式以及一些高级类型的block(比如pdf、equation)等。
- 一些相关的工具扩展包。
优点
- 功能非常完善。由于是notion提供给自己的客户端使用的,所以很多block的数据格式都是比较完善的。比如图片block,notion官方API仅提供了图片的链接,而没有尺寸、位置之类的额外信息。而在私有API中这些都有。类似的block类型包括video、bookmark、embed(maps、figma)等等,公共API都只是提供了数据,而没有样式。另外比如database view,公共API就不包括此类功能。
- 开发相对简单。react-notion-x提供的能力非常完善,与notion相关的桥接基本都完成了,包括数据读取以及block渲染。所以开发者进需要关注如何实现自己的页面组织即可。
不足
- 无文档,没有找到相关的接口说明。自己开发的话得慢慢摸索。如果遇到一些数据拉取不出来的问题可能比较难定位。
- 可维护性存在风险。毕竟Notion官方没有给到外部承诺可以长期使用。
- 隐私问题。需要将页面publish到外网才能访问,如果publish的页面里面包括不想分享的数据的话会有泄露风险。—— 修正:文档上提供了一些private page的解决方案,大致思路就是抓取notion web段的cookie票据来模拟客户端。但Notion票据有效期、更新机制等官方没有给到说明。毕竟不是给外部使用的。
解决方案参考
- reaction-notion-x: 作者提供的example,提供了三个demo可以参考。
- cra:基于create-react-app脚手架的解决方案
- full、minimal:基于next.js脚手架的解决方案
- NotionNext:国人基于react-notion-x的封装。优点是功能组件很完善,模板也非常多,使用范围比较广。除了自部署外,也提供了云托管的部署方案。
- nextjs-notion-starter-kit:使用next.js构建,渲染也是基于reaction-notion-x
- notion-blog:技术方案同上。
公共API
类似twitter、微博等平台,Notion提供了公共API接口给到外部开发者使用,用于围绕Notion构建自己的工具。具体可见notion的开放平台。
基于公共API开发的大致流程如下:
- 申请integration ID。这是访问Notion public API的凭证。
- 页面放开integration的访问权限。表示integration可以访问nition此page下的所有数据。
- 应用开发&部署。
具体流程见Noition上面官网。
如果想多Notion Public API有着更多的了解,可以使用postman工具体验下Notion的数据结构,官方已经封装好了Postman下的API集合。
优点
- 可靠性保障。Notion开放给开发者使用的官方API,接口变化的可能不大。即使变更也会保持向前兼容的能力。
- 文档齐全。
- 隐私保护:页面不需要publish到外网,也不需要抓取cookie之类的hack手段。
不足
- 能力限制。上面也提到了,Notion很多能力没有开放给到外部,比如图片样式等信息,这会导致在页面渲染上没有办法跟Notion自己的客户端(包括web)保持一致。有些能力也没办法实现(比如基于database的view能力)。猜测一方面是因为实现复杂,比如database的各种公式,即使给到外部也不好处理。另一方面是成本之类的考量。比如bookmark block的渲染以及动态更新。这里是要与noiton服务端保持长连接来接收动态push(notion本质上是支持多人编辑的)。
- 实现相对复杂。之所以实现相对复杂是因为了解到目前还没有比较渲染封装比较好的开源解决方案。基本上都是根据notion文档里面各block的样式来自行实现。按我自己的经验,需要了解notion各种block类型的数据结构还挺花时间的。尤其是在嵌套关系的处理上,耗时投入比较大。
解决方案参考
同上,这里也只是列出了一些个人了解过的方案。仅供参考。
- notion-blog-nextjs:使用Next.js和Notion public API构建。
- react-notion-render:准确的说这个只是一个lib,封装了block的渲染。
我的解决方案
我最初是计划使用NotionNext来搭建个人博客,但是体验后发现几个问题:
- 隐私问题:一定要将页面publish到公网,或者添加cookie。这种非官方API的方式让人不太放心,担心哪天遇到问题就麻烦了。
- 没找到合适的主题。个人感觉里面的主题都太过花哨,个人偏好比较简洁的风格。
加上个人对notion的数据结构还比较熟悉了,所以就基于Notion Public API自行实现了一套。于是有了现在的Next-Blogger。主要特点:
- 使用Notion Public API。只要是官方开放出来的Block类型基本都支持。详见readme。
- 支持MDX。可以在页面的code block里面添加mdx,将其渲染为react组件,实现一些丰富的特效来扩展Notion数据格式。比如button跳转。demo参考这里。
更多特性参考readme。建议是有一定开发基础能力的同学可以酌情考虑。
其他
一些付费解决方案