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

SunNav 部署教程:Cloudflare Pages 免费搭建粉色玻璃拟态导航站,D1 存储 + WebDAV 双目标云备份
luoli前言
导航站是最经典的「自建服务入门项目」,但大部分开源方案要么是纯静态页(改个链接要改代码重新构建),要么后端跑在需要买服务器的地方。
SunNav 把这两头都解决在 Cloudflare 免费套餐里:前端 React + Tailwind 跑 Cloudflare Pages,数据存 D1(SQLite),动态接口用 Pages Functions——没有服务器、没有月费,改链接在后台点一下就行。
- 项目地址:https://github.com/love-ztm/SunNav
- 开源协议:MIT(基于 ModernNav 二次开发)
- 技术栈:React 18 · Tailwind CSS · Vite / Cloudflare Pages Functions · D1
它的辨识度在颜值上:粉色玻璃拟态——毛玻璃卡片、主题色自动取色、背景模糊参数全部后台可调,亮暗双主题还支持各自独立的壁纸。功能上除了常规的分类/链接管理,比较有特色的是聚合搜索命令面板(/ 键唤起,带拼音首字母匹配)、私密分类(访问码登录才可见)和 WebDAV 双目标定时云备份(坚果云 / InfiniCLOUD / AList 都能用,备份列表可查、任意一份一键恢复)。
功能一览
前台
- 三级结构:分类 → 子分组 → 链接,玻璃拟态卡片展示
- 聚合搜索:站内 / Google / Bing 等引擎可配置,
/快捷键唤起命令面板(支持拼音首字母模糊匹配) - 三态主题:亮色 / 暗色 / 跟随系统(默认亮色),暗色模式可单独设壁纸
- 外观全可调:每日壁纸、主题色自动取色、背景模糊、卡片毛玻璃参数、卡片宽高 / 图标大小 / 每行卡片数
- 私密分类:访问码登录可见,访客不可见
- 中英双语:未设置时默认中文
- 无闪烁:首屏主题预渲染,刷新和新浏览器打开都不会黑屏
- PWA:可添加到主屏幕
后台(/admin,默认访问码 admin)
- 内容管理:分类/链接增删改、拖拽排序、⭐ 一键指定「打开站点默认显示的分类」
- 外观设置:壁纸、主题色、玻璃质感、布局全参数
- WebDAV 云备份:同时配置两个网盘、定时自动备份 + 保留份数自动清理、备份列表随时查、任意一份一键恢复
- 数据导入导出(JSON)、浏览器书签导入
- 访问码修改(PBKDF2 哈希存储,改后所有已登录设备全部失效)
部署教程(Cloudflare Pages,四步)
第 1 步:Fork 仓库并连接 Pages
- 打开 SunNav 仓库,点右上角 Fork 到自己账号
- Cloudflare Dashboard → Workers 和 Pages → 创建 → Pages → 连接到 Git
- 选择刚 Fork 的仓库,构建配置:
- 框架预设:Vite
- 构建命令:
npm run build - 输出目录:
dist
先直接部署一次(此时还没有数据库,但没关系,下一步补上)。
第 2 步:创建 D1 数据库并建表
- Dashboard → 存储和数据库 → D1 SQL 数据库 → 创建,名字随意(示例用
sunnav-db),建完记下数据库的名称和区域 - 进入该数据库 → 控制台(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 步:登录并改密码
- 访问你的
https://<项目名>.pages.dev - 点右下角齿轮图标进入后台(或直接访问
/admin) - 登录页只需输入访问码:默认
admin - 登录后第一件事:全局设置 → 底部修改访问码
改访问码不是改个字符串那么简单:它以 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 备份:
- 填 WebDAV 地址(必须公网可达——局域网 NAS 地址 Cloudflare 的服务器访问不到)、账号、密码、远程目录
- 可添加第二个目标(双保险:比如坚果云 + AList 各一份)
- 设定每日备份时间与保留份数(超出自动清理最旧的)
- 点保存后可用「立即备份」测试一次,备份列表里能看到每份备份的时间与状态
三条实践建议
- 用应用密码:坚果云走「账户信息 → 安全选项 → 生成应用密码」,别用主密码
- 备份内容:JSON 格式(分类 + 壁纸 + 偏好),与「下载备份文件」的导出格式一致——也就是说手动导出的 JSON 也能直接恢复
- 恢复:备份列表里任意一份一键恢复,覆盖当前站点内容。改了大版本内容前,先手动备份一份
本地开发
1 | npm install |
想改代码再提交,仓库自带完整质量链: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 备份收工。
参考资料
- SunNav 项目仓库(GitHub)
- ModernNav(上游原项目)
- schema-console.sql(D1 控制台专用建表)
- Cloudflare Pages Functions 文档
- Cloudflare D1 文档
- Cloudflare Pages 构建配置











