内容扩展
一、Tina CMS
想了很久是否要集成一个类似 CMS 的管理平台来管理这些文章的内容,终于在这周开始落地了。简单说一下我为什么有这个想法的:由于 DevNow 的定位📌是一个开源的博客项目,所以我在努力的跳出我自己的想法,避免因为一些自己想要的一些功能来让 DevNow 看起来更加的臃肿。集成 Headless CMS 的主要目的是优化现在的工作流和扩展文章内容的丰富度。

具体的集成步骤如下
1. 在项目中集成 Tina
目前项目中已经集成,需要手动改几个配置。具体如下:
1. 更改运行脚本
// 在 package.json 中修改 scripts 的 dev 和 build 即可"scripts": { "dev": "tinacms dev -c \"astro dev\"", "build": "tinacms build && astro check && astro build",}2. 自定义文章结构
根据项目替换 schema ,集体可参考 schema 配置
schema: { collections: [ { name: 'doc', label: 'Posts', path: 'src/content/doc', format: 'mdx', fields: [ { type: 'string', name: 'desc', label: 'Desc', required: true, description: 'The image used for the cover of the post' }, { type: 'boolean', name: 'draft', label: 'Draft', description: 'If this is checked the post will not be published' },
{ type: 'string', required: true, name: 'category', label: 'Category', description: 'Select an category for this post', options: [ ...categories.map((item) => { return { label: item.title, value: item.slug }; }) ] }, // 作者 { type: 'string', name: 'author', label: 'Author', required: true }, // 标签 { type: 'string', name: 'tags', label: 'Tags', required: true, list: true, ui: { component: 'tags' } }, { type: 'string', name: 'image', label: 'Image', required: true }, // 封面图 // 发布时间 { type: 'string', name: 'publishDate', label: 'PublishDate', required: true }, // 是否置顶 { type: 'boolean', name: 'pin', label: 'Pin', required: true }, { type: 'string', name: 'title', label: 'Title', isTitle: true, required: true }, { type: 'rich-text', name: 'body', label: 'Body', isBody: true } ] } ];}运行项目:
pnpm dev然后访问:

看到这样的界面,恭喜你,成功完成了配置 [庆祝][庆祝] 接下来就可以在这里去更新文章的内容了

2. 线上环境集成
通过以上的一些配置,我们已经完成了 local 的配置,接下来我们需要配置一下线上环境,我们可能主要的场景是在线上环境直接进行文件的更新。
Tina 在这里提供了两套解决方案:
这里我选择了 Tina Cloud ,具体的思考一个是自托管的配置成本比较高,需要自己的配置实现:
- Auth Provider:处理 CMS 操作的身份验证和授权。提供由数据库中的用户集合支持的默认Auth.js实现。
- Database Adapter:处理索引和与数据库的交互(例如MongoDB,Postgres等)
- Git Provider:处理将内容保存到
Git
每个模块都是独立的,这意味着您可以选择用不同的实现替换任何模块,或者开发定制解决方案来满足您的特定需求。
当然自托管也是有一些 限制 的,不过限制部分对我来说不是最主要的问题,是上边三个配置的实现成本。还有就是作为一个博客项目,稳定的存储都在 Git 上,所以 Tina Cloud 对我来说是一个更好且简单的实现。
2.1 注册 Tina Cloud 账号

2.2 创建项目

Tina 提供了两种方式,我们选择第一个,选择导入一个已有的项目开始。根据提示的步骤一步一步来就好,

不出意外的话你会看到这样的一个界面。

2.3 配置环境变量
这里我是通过 Vercel 构建项目的,直接在上边配置环境变量就好了,具体如下:

需要注意的是,如果环境变量名改变的话,记得在项目配置在修改对应的值,具体实在
tina/cinfig.ts中:

2.4 把我们集成好的项目分支推到 Git 上进行构建
如果是首次集成的话需要把我们上一步配置的 PUBLIC_GITHUB_BRANCH 这个分支名改成当先对应的分支名,否则 Tian Cloud 无法检测到对应分支,会导致构建失败,等成功推到 mian 主分支的时候,再将 PUBLIC_GITHUB_BRANCH 改回主分支名。
然后回到 Tina Cloud 刷新即可看到:

到这里我们就成功在 DevNow 中集成了 Tina ,后续可以直接通过线上环境访问即可进行文件更新。直接访问我们配置好的域名 https://www.laughingzhu.cn/admin 即可。
也欢迎大家体验开源博客项目 DevNow ,可以提一些反馈建议,当然也可以顺手点个赞👍🏻
详情可参考:
二、Notion
2.1 Notion 设置
2.1.1 创建 Notion 集成
2.1.1.1 什么是内部集成?
内部集成允许 Notion 工作区成员通过 Notion REST API 与工作区交互。每个内部集成都与单个特定工作区绑定,并且只有工作区内的成员可以使用该集成。将内部集成添加到工作区后,成员必须手动授予集成访问他们希望其使用的特定页面或数据库的权限。
在 集成管理 中添加新的机集成,用来获取 token 。

成功创建后入下图,我们可以在 功能 模块中管理集成的权限,这里我们主要是读取内容,然后可以获取到 内部集成密钥 即 PUBLIC_NOTION_TOKEN。

2.1.2 创建 Notion 数据源
目前我们集成只能同步 Database 中的内容,所以我们需要先创建一个 Database。

顶部选中的字符串是 PUBLIC_NOTION_DATABASE_ID ,我们需要将其复制下来,后面会用到。
如图,我们创建一个工作站,然后创建一个 Database 数据源,用来管理我们需要在 DevNow 中展示的文章,为了统一文章的结构,我们在 Database 中添加以下属性:
- title: 文本
- desc: 文本
- publishDate: 创建时间
- image: 图片
- category: 单选
- tags: 文本, 如果有多个,请通过
,分割 - author: 文本
2.1.3 关联集成
我们在对应的工作站中关联相关的集成,这样我们就可以在 DevNow 中通过 Loader 获取相关的内容了。

如图,将我们之前添加的集成关联进来。
2.1.4 创建新文章
如图,我们需要完善所有的属性:

到这里我们 Notion 相关的配置就完事了。
2.2 环境变量配置
如果是通过 Vercel 部署的,可以对应的项目中添加环境变量:
- PUBLIC_NOTION_DATABASE_ID
- PUBLIC_NOTION_TOKEN
对应的值就是我们之前创建的 Database 的 ID 和 token。
如果是私有项目部署的话,可以在 .env 文件中添加相关内容。
2.3 DevNow 配置
在 DevNow 中,我们需要配置相关的 loader 来获取我们的内容,由于数据的不同,我们在数据层也要做一下兼容,我们统一将数据格式化成 src/content/config.ts 中的 SCHEMA 格式。
2.3.1 配置相关的 loader
Notion 的相关 loader 我们通过库 notion-astro-loader 库来实现。
如要接入,请将一下注释打开即可。
...// import { notionLoader } from 'notion-astro-loader';
...// export const NotionDocs = defineCollection({// loader: notionLoader({// auth: import.meta.env.NOTION_TOKEN,// database_id: import.meta.env.NOTION_DATABASE_ID// })//});
export const collections = { doc: Docs,// notion: NotionDocs};2.3.2 数据源格式化
相关文件已经在 DevNow 中添加,如果需要计入 Notion 数据源,同上把注释打开即可。
// import { richTextToPlainText } from 'notion-astro-loader';// import { formatDate } from './utils';
// export const getNotionDocs = (await getCollection('notion')).map((item) => {// return {// id: item.id,// body: item.rendered?.html ?? '',// data: {// title: richTextToPlainText(item.data.properties.title.rich_text),// desc: richTextToPlainText(item.data.properties.desc.rich_text),// category: item.data.properties.category.select?.name || '',// author: richTextToPlainText(item.data.properties.author.rich_text),// tags: item.data.properties.tags.rich_text[0].plain_text.split(','),// image: item.data.properties.image.url,// publishDate: item.data.properties.publishDate.created_time,// pin: false// },// rendered: item.rendered,// filePath: item.id,// collection: item.collection,// };// });
export const latestPosts = [ ...(await getCollection('doc', ({ data }) => { return import.meta.env.PROD ? data.draft !== true : true; })) // 如果需要接入 Notion 数据源,需要将下面的注释去掉 // ...getNotionDocs].sort((a, b) => new Date(b.data.publishDate).valueOf() - new Date(a.data.publishDate).valueOf());2.3.3 遗留问题
由于数据的问题,目前暂时无法实现 Notion 数据源 readTime 计算,所以 Notion 相关文章,暂时不展示。
已经兼容了 Notion 的 headings 和 其他的相关数据。
结果展示
列表页:

详情页:

总结
到这基本就完事了,可以通过这个方式,将 Notion 作为 DevNow 的数据源,来管理我们的文章。
这样可以更方便我们的数据管理,也可以更好的与 Notion 进行集成,让我们的文章更加的丰富。