SunNav 部署教程:Cloudflare Pages 免费搭建粉色玻璃拟态导航站,D1 存储 + WebDAV 双目标云备份

前言

导航站是最经典的「自建服务入门项目」,但大部分开源方案要么是纯静态页(改个链接要改代码重新构建),要么后端跑在需要买服务器的地方。

SunNav 把这两头都解决在 Cloudflare 免费套餐里:前端 React + Tailwind 跑 Cloudflare Pages,数据存 D1(SQLite),动态接口用 Pages Functions——没有服务器、没有月费,改链接在后台点一下就行。

它的辨识度在颜值上:粉色玻璃拟态——毛玻璃卡片、主题色自动取色、背景模糊参数全部后台可调,亮暗双主题还支持各自独立的壁纸。功能上除了常规的分类/链接管理,比较有特色的是聚合搜索命令面板(/ 键唤起,带拼音首字母匹配)、私密分类(访问码登录才可见)和 WebDAV 双目标定时云备份(坚果云 / InfiniCLOUD / AList 都能用,备份列表可查、任意一份一键恢复)。


功能一览

前台

  • 三级结构:分类 → 子分组 → 链接,玻璃拟态卡片展示
  • 聚合搜索:站内 / Google / Bing 等引擎可配置,/ 快捷键唤起命令面板(支持拼音首字母模糊匹配)
  • 三态主题:亮色 / 暗色 / 跟随系统(默认亮色),暗色模式可单独设壁纸
  • 外观全可调:每日壁纸、主题色自动取色、背景模糊、卡片毛玻璃参数、卡片宽高 / 图标大小 / 每行卡片数
  • 私密分类:访问码登录可见,访客不可见
  • 中英双语:未设置时默认中文
  • 无闪烁:首屏主题预渲染,刷新和新浏览器打开都不会黑屏
  • PWA:可添加到主屏幕

后台(/admin,默认访问码 admin)

  • 内容管理:分类/链接增删改、拖拽排序、⭐ 一键指定「打开站点默认显示的分类」
  • 外观设置:壁纸、主题色、玻璃质感、布局全参数
  • WebDAV 云备份:同时配置两个网盘、定时自动备份 + 保留份数自动清理、备份列表随时查、任意一份一键恢复
  • 数据导入导出(JSON)、浏览器书签导入
  • 访问码修改(PBKDF2 哈希存储,改后所有已登录设备全部失效)

部署教程(Cloudflare Pages,四步)

第 1 步:Fork 仓库并连接 Pages

  1. 打开 SunNav 仓库,点右上角 Fork 到自己账号
  2. Cloudflare Dashboard → Workers 和 Pages → 创建 → Pages → 连接到 Git
  3. 选择刚 Fork 的仓库,构建配置:
    • 框架预设:Vite
    • 构建命令:npm run build
    • 输出目录:dist

先直接部署一次(此时还没有数据库,但没关系,下一步补上)。

第 2 步:创建 D1 数据库并建表

  1. Dashboard → 存储和数据库 → D1 SQL 数据库 → 创建,名字随意(示例用 sunnav-db),建完记下数据库的名称和区域
  2. 进入该数据库 → 控制台(Console),把仓库里的 schema-console.sql 的全部内容粘贴进去执行

为什么要区分两份 SQL? D1 控制台解析不了带 -- 注释的 SQL,所以仓库提供了一份无注释版 schema-console.sql 专供控制台粘贴用;带注释的 schema.sql 是给 wrangler CLI 用的(npx wrangler d1 execute sunnav-db --local --file=./schema.sql)。别拿错文件。

建表后一共六张表:config(配置与访问码)、categories、subcategories、links(三级内容)、rate_limits(IP 限流),初始会写入默认访问码 admin 和 schema 版本号。

第 3 步:绑定 D1 到 Pages

Pages 项目 → 设置 → 绑定(Bindings) → 添加 D1 数据库绑定:

  • 变量名:DB(必须叫这个名字,Functions 代码按 env.DB 取)
  • 数据库:选第 2 步创建的 sunnav-db

保存后重新部署一次,绑定才会生效。

第 4 步:登录并改密码

  1. 访问你的 https://<项目名>.pages.dev
  2. 点右下角齿轮图标进入后台(或直接访问 /admin)
  3. 登录页只需输入访问码:默认 admin
  4. 登录后第一件事:全局设置 → 底部修改访问码

改访问码不是改个字符串那么简单:它以 PBKDF2 哈希存储,且修改会轮换 JWT 签名密钥——所有已登录设备(包括你自己)都会失效,需要重新登录。这是安全设计,不是 bug。

到这一步部署完成,一个 pages.dev 域名、免费 HTTPS、全球 CDN 的导航站就上线了。想绑自定义域名:Pages 项目 → 自定义域 → 按 CF 提示加 CNAME 即可(域名托管在 CF 账号下会自动配)。


WebDAV 定时备份说明

这是 SunNav 最有实用价值的功能,配置前先理解它的工作机制,不然会觉得「怎么没准点备份」。

懒触发机制

Cloudflare Pages Functions 没有常驻定时器(不像 Workers 有 Cron Triggers),所以定时备份采用懒触发:页面打开时(以及打开期间每 10 分钟)静默检查一次,发现「已过设定时间且当天还没备份」就自动执行。

推论:

  • 实际备份时刻 = 设定时间之后第一次打开站点。比如设了每天凌晨 3 点,但你 8 点才第一次打开,那备份发生在 8 点
  • 页面保持打开就会准点备份(每 10 分钟的自检兜住)
  • 就算你从来不打开页面,只要哪天打开了,漏掉的备份会自动补上

配置步骤

后台 → 数据 → WebDAV 备份:

  1. 填 WebDAV 地址(必须公网可达——局域网 NAS 地址 Cloudflare 的服务器访问不到)、账号、密码、远程目录
  2. 可添加第二个目标(双保险:比如坚果云 + AList 各一份)
  3. 设定每日备份时间与保留份数(超出自动清理最旧的)
  4. 点保存后可用「立即备份」测试一次,备份列表里能看到每份备份的时间与状态

三条实践建议

  • 用应用密码:坚果云走「账户信息 → 安全选项 → 生成应用密码」,别用主密码
  • 备份内容:JSON 格式(分类 + 壁纸 + 偏好),与「下载备份文件」的导出格式一致——也就是说手动导出的 JSON 也能直接恢复
  • 恢复:备份列表里任意一份一键恢复,覆盖当前站点内容。改了大版本内容前,先手动备份一份

本地开发

1
2
3
4
5
npm install
npx wrangler d1 execute sunnav-db --local --file=./schema.sql # 本地 D1 建表
npm run dev # 纯前端开发(Vite,5173 端口)
npm run build # 生产构建
npx wrangler pages dev ./dist # 本地全栈模拟(Functions + D1 都在)

想改代码再提交,仓库自带完整质量链:npm run verify 一次跑完 ESLint + TypeScript 双 tsconfig 检查 + Vitest + 生产构建。CI 里也有相同的检查(GitHub Actions)。


常见问题

部署后打开白屏或报 500?

九成是第 3 步没做或没重新部署——D1 绑定是在保存后需要重新部署才生效的。确认绑定变量名是 DB(不是 sunnav-db)。

建表 SQL 执行报错?

用的是带 -- 注释的 schema.sql。控制台请用无注释的 schema-console.sql。

后台进不去 / 密码忘了?

默认访问码是 admin。改过但忘了的话,在 D1 控制台执行 DELETE FROM config WHERE key = 'auth_code' 清掉旧码,系统会回退到默认 admin(此操作会删掉配置表中该键,重新登录后再改新码)。

私密分类访客能看到吗?

看不到。私密分类要访问码登录后才可见,访客的首页完全不渲染它——不是「点了才提示密码」,是彻底不出现。

WebDAV 一直失败?

按顺序查:地址是否公网可达(NAS 内网地址不行)→ 是否用了应用密码 → 远程目录是否存在(程序会自动 MKCOL 创建,405/301 属正常中间态)→ 网盘服务商是否限流。

数据在哪、会不会丢?

全部在 D1 数据库里(Cloudflare 托管,免费版每天 10 万次写远超导航站用量)。但要防误操作/误删,WebDAV 备份就是为此准备的——配好双目标定时备份,等于多了两份异地快照。


小结

SunNav 是那种「架构选型很聪明」的项目:导航站这种低写入、低流量、个人用的服务,放在 Cloudflare Pages + D1 上是零成本的最优解;而 Pages Functions 没有定时器的短板,用懒触发 + 前端周期自检绕了过去,WebDAV 双目标 + 保留策略又把数据安全补齐。加上玻璃拟态的颜值和 PWA、命令面板这些体验细节,作为个人起始页已经相当完整。

部署一句话总结:Fork 连 Pages → D1 建表(无注释版 SQL)→ 绑 DB 重新部署 → admin 登录改密 → 配上双 WebDAV 备份收工。


参考资料

推荐链接