开源这个博客的源码 — Nobelium-Plus

date
Apr 26, 2022
slug
nobelium_plus
status
Published
tags
Website
Craft.do
Notion
Next.js
summary
在 Nobelium 的基础上修改而来, 增加了侧边栏大纲, 主题切换, 语言切换, 原生评论, 联系表单等等功能, 还集成了 Craft.do 分享页面到站点中.
type
Post
一个 Nobelium 的衍生版本, 懒得想名字, 所以就叫 Nobelium-Plus 吧. 虽然样式修改了很多, 不过都在原有的 TailwindCSS "框架"内, 新增的功能也没有添加什么复杂的依赖包.
总体来说, 增加了一些实用的功能, 比如:
  • 侧边栏文章大纲
  • 主题实时切换
  • 多语言实时切换
  • 贴合网站风格的评论区
  • 页面过渡动画
  • 支持子页面 (block page)
还有一些很私人化的功能, 像是:
  • 联系表单
  • 微信打赏
  • Telegram 通知集成
  • 周刊页面
比较有意思的是加入了对 Craft.do 的支持, 可以实时生成一个 Craft.do 的页面列表, 并反代了 Craft.do 的分享页面. 具体可以点击导航栏的 笔记 查看效果.
你可以在下面 Github 仓库找到本站的全部代码:
部署过程和 Nobelium 基本一样, 这里简单说一下部署方式.

快速部署

  1. 复制这个 Notion 数据库 到你的空间下, 并分享给所有人.
  1. 点击 Fork 分叉这个项目到你的 Github 账号下.
      • 替换 /public 目录下的资源, 使用你自己的图标 Logo 等等.
  1. 在 Vercel 中部署项目, 并设置以下环境变量:
      • NOTION_PAGE_ID (必填), 你公开分享的 Notion 页面 ID (如图所示).
      • NOTION_SPACES_ID (可选), 你的 Notion 空间 ID, 详情请看下面 子页面解析 部分内容.
      • TELEGRAM_TOKEN (可选), 新增评论和联系表单通知会发到 Telegram 上.
  1. 稍等一会就部署完成了. 如果有问题, 点此快速联系我.

已知问题

  • Safari 移动端的滚动条长度异常.

周刊 Newsletter

Nobelium 本身支持了两种类型的文章, 分别是 Post 和 Page, 对应了博客文章和博客页面, 我新增了一个类型 Newsletter, 它和 Post 类似, 但不会出现在首页的博客文章列表中.
当你在自己的 Notion 数据库里新建一个页面时, Type 选择 Newsletter (没有就在数据库里新建一个) 时, 该页面就不会显示在博客文章列表中, 而是显示在周刊 Newsletter 那一页.

多语言

为了站点轻便, 多语言这个功能没有使用其他依赖库, 只在 Next.js 原生 i18n 支持下配合 next/router 实现了这个功能.
如果你要新增或者修改网站的语言或者文案, 只需要打开 lib/lang.js 修改其中的内容即可. 值得一提的是, 目前全站的文字内容都已经"提炼"到这个文件, 也就是说你可以在这个文件中修改全站每一处的文字内容.
如果需要新增语言, 首先在 lang.js 后面按格式添加你的语言和相对应的翻译, 然后在 next.config.js 中修改 i18n 的配置.
如下所示, 请确保两个文件中语言的缩写一致, 举个例子:
  • 如果你在 lang.js 中新增了新语言, 名为 zh-HK
  • 那么在 next.config.js 中也需要配置一样的语言缩写 zh-HK 才会生效
// lib/lang.js export const lang = { zh: { ... }, zh-HK: { ... }, en: { ... }, ja: { ... }, es: { ... } } // next.config.js i18n: { locales: ['en', 'zh', 'zh-HK'], defaultLocale: 'zh', localeDetection: false },
目前的语言切换按钮只支持在两种语言之间切换. 需要修改切换的语言, 可以编辑 components/LangSwitcher.js 里的表达式, 当前是中英两个语言之间切换.
<Link locale={locale === 'en' ? 'zh' : 'en'} passHref href={asPath}>

联系表单

联系表单会把提交的内容发送到 Telegram 里, 即便访客在国内也可以把内容发送到 Telegram. 因为它是通过 Vercel 的边缘函数给 Telegram 发送信息的, 所以不存在 Telegram 被墙发不出去的情况.
要配置这个表单, 你需要先创建一个 Telegram 机器人. 然后和 @BotFather 机器人交互, 获取你的 bot 的 API token.
类似 Nobelium 部署时添加的 NOTION_PAGE_ID 环境变量一样, 你需要在 Vercel 后台添加一个变量, 名为 TELEGRAM_TOKEN, 值就是你申请到的 API token.
最后修改 blog.config.js 里的 telegramChatId 那一项为你的 chat id (可以询问 Telegram 机器人 @chatIDrobot), 这样你的联系表单就配置好了.
💡
记得要和你创建的机器人互动一下, 给它发个 /start, 不然机器人无法给你发消息.

评论区

因为 Nobelium 已经支持的评论系统似乎都不太好用, 或者和网站主题风格不搭. 所以就自己动手搞了一个, 这样评论区看起来和网站风格比较一致.
评论内容存储在 Supabase, 免费版已经完全够用. 要配置这个评论区, 你需要注册一个 Supabase 的账号, 然后新建一个数据库, 再新建一张名为 comments 的表, 表结构如下:
id - int8 name - text email - text postURL - text comment - text created_at - timestamp show - boolean
表结构参考
表结构参考
然后在数据库的 settings —> api 页面复制 anon keyURL, 把它粘贴到 blog.config.js 文件里的 supaCommentsConfig 那两行中, 并修改 providersupacomments.
是 anon key, 不是 secret, 不要复制错了.
是 anon key, 不是 secret, 不要复制错了.
provider: 'supacomments', // leave it empty if you don't need any comment plugin supaCommentsConfig: { supabaseUrl: '', // The url of your Supabase instance supabaseAnonKey: '', // The anonymous key of your Supabase instance },
这样评论区就配置完了. 值得一提的是, 如果你配置了 TELEGRAM_TOKEN, 那么当有人发表评论时, 你的 Telegram 同样也会收到通知.
目前评论区的代码还没开源(快了), 因为有一些细节还没搞定, 但是并不影响使用. 打包后的代码我放在了 public/comment 目录, 目前已经适配了中英两个语言.

💡
请注意你使用的 Supabase 数据库, 如果有敏感数据建议你开启 RLS(行级安全), 否则任何人都可以修改你的数据库. 但如果这个实例只是用于网站评论, 你也可以无视这个提醒, 毕竟评论数据本来就是要公开的.
行级安全配置示意, 只允许查看和插入数据(可选)
行级安全配置示意, 只允许查看和插入数据(可选)

💡
出现 “data-url 配置错误” 的信息, 请检查你的 blog.config.js 文件里的 link 那一项. 浏览器访问的域名和 link 中的域名一致时, 评论区才会显示.

子页面解析

因为子页面在 Nobelium 数据库中没有固定的 slug, 不能像博客文章那样通过 slug 映射到对应的 page id, 所以子页面只能通过 page id 访问, 这无法适应预渲染(SSG)的机制.
所以为了安全起见, 你应该设置 NOTION_SPACES_ID 这个环境变量, 否则任何人都可以通过你的域名解析他的 Notion 页面.
你可以通过下面步骤找到你的 NOTION_SPACES_ID:
  • 在 Vercel 或其他地方成功部署后, 打开你的站点, 点击打开任意一篇文章
  • 鼠标右键, 选择”显示网页源代码”, 在源代码页面搜索 space_id 这个关键字, 第一个找到的就是你要的 NOTION_SPACES_ID 啦.
  • 在 Vercel 项目设置的环境变量里填上 NOTION_SPACES_ID 和对应值即可.
如此一来, 站点只能解析你指定的 Notion 空间下的页面, 别人无法通过你的站点解析任意 Notion 页面了.
🎉
这是一个子页面示例

自定义 Logo

我的站点 Logo 用的是 svg 格式的图片, 很多都直接写进代码里了.
  • public 文件夹里的 favicon 图标都换成你自己的.
  • 左上角 Logo 可以在 Header.js 中修改.
  • 首页右侧 Logo 在 Avatar.js 文件里, 如果你没有 svg 格式的图片, 请参考这个 猫猫头的代码 (用猫猫头的这个 Avatar.js 文件替换原来的 Avatar.js 文件就可以了, 最后只需要修改一下猫猫头的图片链接):
notion image
notion image

Craft.do 分享页面

Craft.do 同样是我很喜欢用的一个软件, 而且 Craft.do 的分享页面做得很出色, 早在去年我便写过一个 Cloudflare Worker 的脚本用来自定义 Craft.do 分享页面的域名. 后来我发现 Next.js 也支持一定程度的 rewrite, 可以做到类似 Cloudflare Worker 的功能, 于是我便把 Craft.do 也整合到这个博客中了.
配置方式很简单, 在 Craft.do 新建一个文档, 设为公开, 格式参考这个页面:
把分享链接粘贴到 blog.config.js 里的 craftConfigShareUrl 就可以了, 网站会自动生成笔记页面.
要修改笔记页面左上角的 logo 只需要在 public 下替换那个 favicon.svg 图片. 要修改右上角的菜单内容也是在 blog.config.js 里修改 notes 相关的部分即可.
notes: '左蓝的笔记', notesNav: { index: '全部笔记', blog: '返回博客', contact: '联系我' }, notesLink: { index: '/', blog: '<https://zuolan.me>', contact: '<https://zuolan.me/contact>' },
如果你的 Craft.do 配置页面格式不正确, 在生成的笔记页面底部会有一行字提示你. 自己核对一下 craftConfigShareUrl 页面内容的格式.

最后, 这里还有一个去掉了 Notion 相关代码的版本, 只保留了 Craft.do rewrite 的相关功能. 我把它也开源出来, 供有需要的人参考使用.
 
对于本文内容有任何疑问, 可与我联系.