站点做到第七个页面时,我同时收到两条反馈:页脚最后一项是"关于",顶栏最后一项是"我";命令面板里搜"工艺",排第三的却是"复盘"。
三个地方,三套顺序。它们都曾经正确过——每加一个页面,我改了最先看到的那一处。
一次加页面,要改三处
SiteNav.tsx 自己写一遍
Footer.tsx 自己写一遍
CommandPalette 自己写一遍手写三份的成本不在写,而在顺序会漂。没有哪一次是明确改错的,都是"这回只补了顶栏、下回补页脚"的累积。
顺序收进一个数组
src/lib/nav.ts 现在只有一个导出:
export const navLinks = [
{ to: '/notes', label: '笔记' },
{ to: '/import', label: '导入' },
{ to: '/retro', label: '复盘' },
{ to: '/life', label: '生活' },
{ to: '/craft', label: '工艺' },
{ to: '/me', label: '我' },
{ to: '/about', label: '关于' },
] as const顶栏、页脚、命令面板都 map 它。as const 不是装饰:它让 to 保留字面量类型,路径写错在编辑器里就能看见,而不是等运行时 404。
导航不等于路由
站里有 14 条路由(含 404 兜底),进导航的只有 7 条。剩下的分三类:
| 类别 | 例子 | 处理 |
|---|---|---|
| 入口 | /notes /retro /craft | 进 navLinks |
| 可达但不占位 | /archive(旧地址跳转)、/local(本地文档) | 不进导航,靠跳转或列表链接到达 |
| 详情页 | /notes/:slug /life/:id | 由列表进入,永远不进导航 |
/archive 是个值得留下的例外。归档已经并进 /notes?view=timeline,按常理该删掉路由,但它曾经被预渲染、进过 sitemap,也可能躺在别人的收藏夹里。删掉之后访问会落到 404.html——状态码 404、标题"页面不存在",看起来像站点坏了。
所以它仍然被预渲染,只是 noindex:有文件、能跳转、不参与索引。导航里不出现它,因为它不是目的地,只是旧地址的转运站。
Dock 从导航降级为展品
第一版的底部 Dock 是全站导航,视觉上是这个项目最出彩的组件。后来它被降级到 /craft 当展品,原因不是性能:
- Dock 的隐喻是应用切换,而站的核心行为是阅读与检索;
- 它是常驻浮层,在三千字的长文里会一直压着正文底部;
- 移动端还要额外处理安全区与手势冲突,收益却只有"好看"。
代价是真实的:首屏少了一个视觉锤。换来的方案是排版、留白和一次 8px 入场位移——它们不抢注意力,但也不需要读者去关掉。
怎么检查有没有漂
没有写自动校验,检查方式是并排看两张表:src/App.tsx 的 <Route> 列表,和 navLinks 的数组。差集应该只剩上表里的第二、三类。
真正的护栏是结构而不是脚本:只要顺序只有一个来源,就不存在"忘了同步"这个动作。