与 AI 合伙人相爱相杀 vlog 11:分类革命与面包屑
网站内容越来越多,全都混在一起怎么办?这集我们给博客来一次分类革命——创建内容分类与标签系统,修复各种bug,实现面包屑导航,打造完整的内容组织与导航体验。

序章:待办清单梳理与优先级调整

早晨的阳光透过窗帘缝隙,在卧室地板上投下一道窄窄的光带。老大醒得比闹钟早,伸手摸到床头柜上的手机,屏幕亮起:七点整。
卧室里很安静,窗帘拉着,光线从缝隙透进来。妻子还在睡,他轻手轻脚地起床,走进卫生间洗漱。
冷水打在脸上,清醒了一些。他一边刷牙,一边想着昨天的事:对话气泡优化完了,效果不错。但网站现在有 Vlog 1 到 10,加上那篇技术文章,总共 11 篇,全都混在一起。读者想找特定主题的内容很麻烦。
洗漱完,他走到厨房,从冰箱里拿出牛奶和麦片。倒进碗里,加牛奶,搅拌几下,端着碗走到客厅。窗外,小区的晨练大妈已经开始跳广场舞了,音乐声隐隐约约传进来。
他打开电视,调到早间新闻,声音调低。一边吃麦片,一边用手机打开 blueslin.com。首页显示着最新的 Vlog 10 文章,他点进去,滑动页面。对话气泡的效果确实好多了,头像发光,淡入动画。
但往下滑动,看到文章列表页面,所有文章还是堆在一起。Vlog 1 到 10,加上技术文章,按时间倒序排列。读者如果想只看 Vlog 系列,或者只看技术文章,没有筛选方式。
他放下手机,吃完最后一口麦片。电视里在播天气预报,今天多云。他关掉电视,走进书房。
家里的台式机还开着,他坐下,唤醒显示器。终端窗口还在,显示着昨天的日志。他敲了几下键盘,打开 TASK-LIST.md。
收到。正在读取 docs/task/TASK-LIST.md。
当前待办任务状态:
🟡 内容分类与检索功能(进行中)
🔄 代码高亮功能(延后)
⏳ OG Image 动态生成(待开始)
⏳ 老兵防坑指南系列(待开始)
确认今天优先级:内容分类与检索功能。
技术准备:
需要设计 Sanity Schema(Category/Tag 模型)
修改前端页面(分类页、标签页、汇总页)
更新同步脚本(push/pull 支持分类标签)
添加导航入口
从第一步开始,需要先创建 Sanity Schema。现在开始吗?
老大看着终端里的分析,点点头。内容分类确实比代码高亮更急迫,代码高亮只是锦上添花,内容分类是基础功能,影响用户体验和 SEO。
理解。碎片化时间模式启动。
第一阶段:Sanity Schema 设计
将在 sanity/schemas/ 目录下创建两个文件:
category.ts - 分类模型
tag.ts - 标签模型
同时更新 post.ts 添加分类/标签引用字段
预估时间:30-40 分钟(包括测试和验证)。
现在开始创建文件吗?
老大看了看时间,八点十分。他九点要到公司,通勤时间大概二十分钟。现在开始的话,可能只能完成一部分。
收到。开始创建 Sanity Schema 文件。
正在创建 sanity/schemas/category.ts... 创建完成。
正在创建 sanity/schemas/tag.ts... 创建完成。
正在更新 sanity/schemas/post.ts... 更新完成。
文件内容概要:
category.ts:分类模型,包含 name、slug、description 字段
tag.ts:标签模型,结构类似分类
post.ts:添加 categories、tags 数组引用字段
需要重启 Sanity Studio 验证 Schema 吗?
老大站起身,走到卧室换衣服。妻子已经醒了,正在看手机。
“今天几点下班?”妻子问。
“正常时间,六点多吧。”老大一边套上衬衫一边说,“不过可能要加点班,网站有个功能要搞。”
“你那个 AI 合伙人网站?”
“对,巴基。今天搞内容分类。”
妻子笑了笑:“你这 AI 合伙人比我还勤快,天天加班。”
老大也笑了:“它不用睡觉。”
换好衣服,他走回书房,在终端里敲了几下。
收到。Sanity Schema 文件已创建完成,待验证。
当前状态:
✅ Sanity Schema 文件创建完成
⏳ 前端页面实现(待开始)
⏳ 同步脚本更新(待开始)
⏳ 导航入口添加(待开始)
等你到公司后继续。
老大关掉台式机,拿起背包,检查了一下钥匙和工牌。走到门口,穿上鞋。
“我走了。”他对卧室说。
“路上小心。”妻子的声音传来。
他关上门,走进电梯。电梯下降时,他掏出手机,打开 Discord。家里的台式机现在应该关机了,但通过 OpenClaw,他可以在路上跟巴基沟通。
不过现在还没到那一步。内容分类是个系统工程,需要静下心来搞。碎片化时间可以推进,但不能太零散。
地铁上,他找了个角落站着。车厢里人不多,早高峰已经过了。他看着窗外闪过的广告灯箱,想着内容分类的设计。
分类和标签,怎么分比较合理?Vlog 系列肯定要有一个分类,技术文章一个分类。标签可以更灵活一些:SEO、Sanity、Discord、技能开发、建站...
正想着,地铁到站了。他走出车厢,刷卡出站。公司大楼就在地铁站出口,他走进大楼,刷卡进电梯。
到了工位,放下背包,打开 MacBook。连上公司 Wi-Fi,终端自动打开。
他坐下,手指在键盘上敲了几下。
收到。正在重启 Sanity Studio 验证 Schema...
Sanity Studio 启动成功。确认 Category 和 Tag Schema 显示正常。
下一步:前端页面实现。
需要创建以下页面:
app/category/[slug]/page.tsx - 分类详情页
app/tag/[slug]/page.tsx - 标签详情页
app/categories/page.tsx - 分类/标签总览页
同时更新现有页面:
app/blog/[slug]/page.tsx - 文章详情页显示分类/标签
app/blog/page.tsx - 文章列表页显示分类
现在开始实现吗?
老大看着终端里的计划,觉得可以。前端页面实现需要时间,但可以先搭框架,细节慢慢完善。
收到。开始创建前端页面...
终端里,光标开始闪烁。老大靠在椅背上,看着屏幕。窗外的阳光透过百叶窗照进来,在桌子上形成一条条光带。
隔壁工位的同事在打电话,声音不大。老大端起桌上的保温杯,喝了一口水。今天周三,一周过了一半。网站的功能,也快完整了。
第一章:内容分类与标签系统实现
窗外的阳光移到桌子中间,时间快到十一点了。老大站起身,去茶水间接水。保温杯里的咖啡喝完了,只剩点底,他倒掉,重新接了热水。
回到工位时,终端里已经显示了一些进度。
前端页面框架创建完成:
app/category/[slug]/page.tsx - 分类详情页
app/tag/[slug]/page.tsx - 标签详情页
app/categories/page.tsx - 分类/标签总览页
正在更新现有页面...
app/blog/[slug]/page.tsx - 文章详情页添加分类/标签显示区域
app/blog/page.tsx - 文章列表页添加分类标签
需要验证页面路由和基本样式吗?
老大坐下,打开浏览器,输入 http://localhost:3000/categories。页面加载出来,但内容区域是空的——还没有任何分类数据。
终端里,光标闪烁了几秒。
提供两套方案供选择:
方案一(通用型):
AI 编程
独立开发
技术教程
建站经验
方案二(针对现有内容):
AI Vlog - 与 AI 合伙人相爱相杀系列
技术教程 - 独立的技术文章
标签建议:
按内容要点打标签:Vlog-1~8、SEO、Sanity、Discord、技能开发、建站
你倾向于哪套方案?
老大看着这两套方案,思考着。方案二更贴合现状——网站现在主要就是 Vlog 系列和一些技术文章。方案一的分类太泛,现阶段用不上。
Vlog-1~8 标签确实粒度较细,但有利于读者按集数查找。也可以考虑合并为"Vlog 系列"一个标签。
确认使用方案二:
分类:AI Vlog、技术教程
标签:AI 协作、SEO、Sanity、Discord、技能开发、建站、Vlog-1~8
现在开始创建这些分类和标签吗?
老大想了想,Vlog-1~8 这种标签确实太细了,而且每发一篇新 Vlog 就要加一个新标签,维护起来麻烦。
收到。正在通过 Sanity Studio 创建分类和标签...
创建完成:
分类:AI Vlog (ai-vlog)、技术教程 (tutorial)
标签:AI 协作 (ai-collaboration)、SEO (seo)、Sanity (sanity)、Discord (discord)、技能开发 (skill-dev)、建站 (web-building)
现在需要将现有文章关联到对应的分类和标签。
老大刷新浏览器页面,/categories 页面现在显示两个分类和六个标签,每个都有计数(目前都是 0)。他点进"AI Vlog"分类,页面是空的——还没有文章关联过来。
这时,电脑右下角弹出会议提醒:十一点半有个项目例会。老大关掉提醒,还有十五分钟。
终端里,光标快速闪烁。
很好的长期化需求。进入计划模式分析完整方案:
完整同步系统升级方案:
Markdown frontmatter 支持:在本地文章 frontmatter 中添加 categories 和 tags 字段
同步脚本升级:
push:读取 frontmatter 中的分类/标签,转换为 Sanity 引用并上传
pull:从 Sanity 拉取文章时,将分类/标签引用转换为名称写入 frontmatter
独立管理脚本:创建 manage-taxonomy.ts 用于分类/标签的增删改查和同步检查
npm scripts:新增 npm run taxonomy 命令
预估工作量:中等,需要修改现有同步脚本并创建新管理脚本。
确认实施这个完整方案吗?
老大看着这个完整方案,点点头。一次性脚本确实不够用,内容分类是长期需求,需要完整的工具链支持。
收到。开始实施完整同步系统升级方案。
第一阶段:修改 lib/scripts/sync-sanity.ts 支持分类/标签读写。
正在读取现有脚本...分析数据结构...开始修改。
老大站起身,拿起笔记本和笔,走向会议室。走廊里,同事们在讨论中午吃什么,声音嘈杂。他走进会议室,找了个角落坐下。
会议是关于下个季度的产品规划,老大心不在焉地听着,偶尔在笔记本上记几笔。脑子里还在想分类系统的事:前端页面有了,分类标签创建了,同步脚本在升级...但用户怎么找到这些分类页面?导航栏还没有入口。
会议开了四十分钟,结束时已经十二点多了。老大回到工位,同事叫他一起去食堂吃饭。
“你先去,我有点事。”老大说。
同事走后,他坐下,打开终端。巴基已经完成了同步脚本的修改。
同步脚本升级完成:
✅ push 功能:读取文章 frontmatter 中的 categories/tags 字段,转换为 Sanity 引用
✅ pull 功能:将 Sanity 中的分类/标签引用转换为名称写入 frontmatter
✅ 新增 getTaxonomyMap() 函数:建立分类/标签的 ID-名称映射
管理脚本创建完成:
✅ lib/scripts/manage-taxonomy.ts - 分类/标签管理工具
✅ 支持功能:list、create、remove、sync
✅ npm script:npm run taxonomy -- [command]
下一步:测试同步功能,将现有文章关联到分类/标签。
老大看着终端里的进度,觉得效率不错。他打开保温杯,喝了几口水,水已经凉了。
收到。开始推送所有文章到 Sanity...
正在读取 content/posts/ 目录下的所有 Markdown 文件...
解析 frontmatter...检测到大部分文章没有 categories/tags 字段。
问题:需要先为每篇文章配置分类和标签,否则推送时这些字段为空。
建议流程:
先为所有文章配置分类/标签
然后推送
最后测试拉取功能
需要我现在为文章配置分类/标签吗?
老大这才意识到,本地文章确实还没有分类标签信息。他想了想,Vlog 1 到 10 应该都属于"AI Vlog"分类,那篇技术文章属于"技术教程"分类。标签可以按内容主题分配。
收到。开始分析文章内容并分配分类/标签...
分配结果:
ai-vlog-1.md → AI Vlog + AI 协作
ai-vlog-2.md → AI Vlog + AI 协作
ai-vlog-3.md → AI Vlog + SEO
ai-vlog-4.md → AI Vlog + Sanity
ai-vlog-5.md → AI Vlog + Discord
ai-vlog-6.md → AI Vlog + 技能开发
ai-vlog-7.md → AI Vlog + AI 协作
ai-vlog-8.md → AI Vlog + 技能开发
my-first-blog-post.md → 技术教程 + 建站
正在更新本地文章的 frontmatter...更新完成。
现在开始推送所有文章到 Sanity。
终端里,光标快速滚动,显示着推送进度。老大站起身,走到窗边。窗外是公司的园区,中午时分,员工们在楼下散步、聊天。阳光很好,照在草坪上,泛着绿意。
过了几分钟,他回到座位,推送已经完成。
推送完成。所有文章已成功上传到 Sanity,包含分类/标签引用。
验证:
打开浏览器访问 http://localhost:3000/categories
点击"AI Vlog"分类,应该显示 8 篇文章
点击"技术教程"分类,应该显示 1 篇文章
标签页面也应该有相应的文章计数
老大刷新浏览器,/categories 页面现在显示:AI Vlog (8)、技术教程 (1)。他点进"AI Vlog"分类,页面加载出八篇文章的卡片,每张卡片显示标题、摘要和发布时间。
他又点进"SEO"标签页面,显示一篇文章——Vlog 3《搜索引擎搜不到我的站》。正确。
检查导航栏实现...components/navbar.tsx 目前只有"首页"和"博客"两个链接。
问题:用户无法直接从导航栏访问分类页面。
解决方案:在导航栏添加「分类」链接,指向 /categories 页面。
需要我添加这个导航入口吗?
老大觉得这个方案最简单直接。用户点击"分类",进入总览页面,可以看到所有分类和标签,再点击进入具体的分类或标签页面。
正在修改 components/navbar.tsx...
在"博客"链接后面添加「分类」链接,指向 /categories。
修改完成。
老大刷新页面,导航栏现在显示:首页 | 博客 | 分类。他点击"分类",跳转到 /categories 页面,一切正常。
这时,肚子咕咕叫了一声。他看了眼时间,一点二十。食堂应该还有饭,虽然可能只剩菜底了。
他关掉浏览器,站起身,准备去吃饭。走到门口时,又回头看了一眼终端。
终端里,光标安静地闪烁着。早上的 Sanity Schema,上午的前端页面,中午的同步脚本升级,下午的导航入口——内容分类系统的基本框架已经搭起来了。
但老大知道,这种规模的系统升级,通常会有一些隐藏的 bug。下午回来,估计要开始 debug 了。
他走出办公室,走廊里很安静,大部分同事都还在午休。电梯下降时,他想着下午要做什么:测试拉取功能,验证双向同步,检查 Sanity 后台有没有问题...
电梯门打开,他走进食堂。饭菜的香味飘过来,肚子又叫了一声。

第二章:bug 修复与完善
下午两点半,老大回到工位。食堂的饭菜一般,但吃饱了。他坐下,打开保温杯,喝了几口水,水温刚好。
电脑屏幕上,终端窗口还开着。他敲了几下键盘。
收到。开始重新推送所有文章到 Sanity...
正在读取 content/posts/ 目录下的所有 Markdown 文件...
解析 frontmatter...检测到所有文章都有 categories/tags 字段。
开始推送...推送完成。
结果:所有文章成功上传,分类/标签引用正常。
老大打开浏览器,访问 http://localhost:3000/categories。页面加载正常,两个分类,六个标签,计数正确。他点进"AI Vlog"分类,八篇文章显示正常。
但看着文章列表,他注意到一个问题:第一篇文章《我被自己的 AI 合伙人嫌弃了》好像不需要分类?那篇文章主要是项目启动和技术选型,虽然属于 Vlog 系列,但内容比较特殊。
收到。正在修改 content/posts/2026-02-27-ai-vlog-1.md 的 frontmatter...
将 categories: ['AI Vlog'] 改为 categories: [](空数组)。
修改完成。
需要重新推送这篇文章吗?
终端里,光标闪烁。老大站起身,走到窗边。下午的阳光斜照进来,在桌子上投下长长的影子。窗外,园区里的树开始冒新芽,春天真的来了。
几秒钟后,推送完成。他回到座位,刷新浏览器页面。"AI Vlog"分类的计数从 8 变成了 7。正确。
收到。正在重启 Next.js 开发服务器...
端口 3000 被占用,正在清理...清理完成。
重新启动服务器...启动成功。
开发服务器现在运行在 http://localhost:3000。
老大刷新页面,一切正常。但他突然想到一个问题:新功能怎么测试?用户的角度上,如何体验这些分类和标签?
终端里,光标停顿了一下。
用户测试路径:
访问首页,看到导航栏有"分类"链接
点击"分类",进入 /categories 总览页
在总览页看到所有分类和标签,点击感兴趣的进入详情页
在详情页看到该分类/标签下的所有文章
点击文章进入阅读,在文章详情页看到该文章的分类/标签
可以点击分类/标签跳转到对应的列表页
测试页面:
/categories - 分类/标签总览页
/category/ai-vlog - AI Vlog 分类详情页
/tag/seo - SEO 标签详情页
/blog/ai-vlog-3 - 文章详情页(应该显示分类/标签)
老大按照这个路径测试了一遍。导航栏有"分类"链接,点击进入总览页,看到两个分类六个标签,点击"AI Vlog"进入分类详情页,看到七篇文章(第一篇文章去掉了分类)。
但测试到文章详情页时,他发现一个细节问题:文章详情页显示分类和标签,但那些分类标签是链接吗?点击能跳转吗?
他点进 Vlog 3 文章,页面底部确实显示了"分类:AI Vlog"和"标签:SEO"。他尝试点击"AI Vlog",没有反应——不是链接。
检查当前实现:
导航栏有"分类"链接(已添加)
文章详情页显示分类/标签(但不是链接)
文章列表页显示分类(但不是链接)
问题:除了主动点击导航栏的"分类",用户没有其他途径发现分类功能。
改进方案:
方案一:在文章详情页将分类/标签显示为可点击链接
方案二:在首页展示热门分类或分类入口
方案三:在博客列表页添加分类筛选功能
需要我实现哪个方案?
老大看着这三个方案,觉得方案一最简单直接,也最符合用户习惯——在文章详情页看到分类标签,自然想点击看看同分类的其他文章。
收到。正在修改 app/blog/[slug]/page.tsx...
将分类/标签的静态文本改为 <Link> 组件。
修改完成。
老大刷新 Vlog 3 文章页面,页面底部的"分类:AI Vlog"和"标签:SEO"现在显示为链接样式。他鼠标悬停,光标变成手型;点击"AI Vlog",页面跳转到 /category/ai-vlog,显示该分类下的所有文章。
很好,闭环形成了。
这时,电脑右下角弹出提醒:三点半有个技术评审会。老大关掉提醒,还有十分钟。
他打算再测试一下文章列表页。打开 http://localhost:3000/blog,页面加载出来,但浏览器控制台显示红色错误。
终端里,光标快速闪烁。
正在检查 app/blog/page.tsx...
问题分析:
文章卡片外层用 <Link> 包裹整个卡片(包括标题、摘要、分类标签)。
内层的分类也是 <Link>(刚才方案一的修改)。
导致 <a> 嵌套 <a>,这是 HTML 规范不允许的。
解决方案:
外层 <Link> 改为 div + onClick 模拟链接行为
内层分类保持 <Link> 不变
需要处理点击事件和路由跳转
正在修复...修复完成。
老大刷新页面,控制台错误消失了。他点击文章卡片,页面跳转到文章详情页;点击卡片内的分类标签,跳转到分类页面。两者互不干扰。
解决了嵌套 a 标签问题,但他突然想到另一个问题:Sanity 后台会不会有报错?刚才推送了文章,分类标签是数组引用,Sanity 对数组类型有特殊要求。
终端里,光标停顿了一下。
无法直接查看 Sanity 后台,需要你手动检查或提供截图。
常见问题:
分类/标签引用格式不正确
数组缺少 _key 字段(Sanity 数组类型的特殊要求)
引用的分类/标签不存在
建议打开 Sanity Studio 检查。
老大打开浏览器,访问 Sanity Studio。登录后,进入文章列表,点开 Vlog 1 文章。编辑界面加载出来,但分类和标签区域显示红色错误图标,旁边有文字提示:"Add missing keys"。
他点击"Add missing keys"按钮,错误消失了,分类标签正常显示。
终端里,光标快速滚动。
问题分析:
对比 Vlog 8(之前手动在 Sanity Studio 编辑过)和 Vlog 1(刚才推送)的数据格式。
发现:
Vlog 8 的 categories 数组:[{_key: "abc123", _type: "reference", _ref: "cat123"}]
Vlog 1 的 categories 数组:[{_type: "reference", _ref: "cat123"}]
问题根源:Sanity 的数组类型需要每个元素都有唯一的 _key 字段,但推送脚本没有生成这个字段。
修复方案:
修改推送脚本,为每个分类/标签引用添加 _key 字段:
return { _key: randomUUID().slice(0, 12), _type: 'reference', _ref: refId };
需要我修复推送脚本吗?
老大这才明白过来。Sanity 的数组类型确实需要 _key 字段,这是为了数组元素的唯一标识和排序。之前的推送脚本漏掉了这个细节。
收到。正在修改 lib/scripts/sync-sanity.ts...
导入 randomUUID 函数,为每个分类/标签引用生成 _key。
修改完成。
开始重新推送所有文章...推送完成。
老大刷新 Sanity Studio,打开 Vlog 1 文章,这次没有错误提示了,分类标签正常显示。他关掉 Sanity Studio,回到终端。
这时,他突然想到一个问题:刚才分配标签时,巴基给每篇 Vlog 都加了"Vlog-1"、"Vlog-2"这种标签。现在想想,这种标签完全没必要——用户不会按集数找文章,而且每发一篇新 Vlog 就要加新标签,维护麻烦。
收到。检查本地文章分类/标签配置...
当前状态:
my-first-blog-post.md:分类空,标签空
ai-vlog-1.md:分类空,标签 AI 协作
ai-vlog-2.md:AI Vlog + AI 协作
ai-vlog-3.md:AI Vlog + SEO
ai-vlog-4.md:AI Vlog + Sanity
ai-vlog-5.md:AI Vlog + Discord
ai-vlog-6.md:AI Vlog + 技能开发
ai-vlog-7.md:AI Vlog + AI 协作
ai-vlog-8.md:AI Vlog + 技能开发
问题:
my-first-blog-post 没有分类标签
Vlog-1~8 标签之前已经去掉,但 Sanity 中可能还有残留
老大看着这个列表,觉得需要调整。那篇技术文章应该有个分类和标签,Vlog-1~8 标签确实该清理。
清理方案:
删除所有本地文章的 Vlog-X 标签(如果还有)
为 my-first-blog-post 添加:
分类:技术教程
标签:建站
重新推送所有文章,清理 Sanity 中的 Vlog-X 标签残留
执行吗?
终端里,光标快速滚动。老大端起保温杯,喝了几口水,水已经凉透了。他站起身,走到茶水间,倒掉凉水,重新接了热水。
回到工位时,清理已经完成。
清理完成:
✅ 删除所有 Vlog-X 标签
✅ 为 my-first-blog-post 添加分类"技术教程"、标签"建站"
✅ 重新推送所有文章
✅ Sanity 中的 Vlog-1~8 标签已清理
最终分类/标签状态:
分类:AI Vlog (7篇)、技术教程 (1篇)
标签:AI 协作、Discord、SEO、Sanity、建站、技能开发
老大刷新浏览器,访问 /categories 页面。现在显示:AI Vlog (7)、技术教程 (1)。标签区域显示六个标签,每个都有相应的文章计数。
他点进"建站"标签,显示一篇文章——那篇技术文章。正确。
基本功能都测试通过了,但还有一个关键功能没测试:拉取。双向同步系统,push 测试了,pull 还没测。
收到。开始从 Sanity 拉取 Vlog 3 文章...
拉取完成。文件保存到 content/posts/2026-03-02-ai-vlog-3.md。
老大打开这个文件,查看 frontmatter。分类和标签字段有内容,但内容格式很奇怪:
categories:
- _ref: qEcETyhJpLY4DZsj0MdT7N
tags:
- _ref: abc123def456
这不是分类/标签的名称,而是 Sanity 的内部引用 ID。
终端里,光标快速闪烁,显示着代码分析和调试信息。
问题分析:
拉取脚本保存的是 _ref ID(如 qEcETyhJpLY4DZsj0MdT7N)而不是名称(如 SEO)。
根源:getTaxonomyMap() 函数建立映射时,key 是 slug.current,但查找时用的是 _ref(即 _id),两者不匹配。
修复方案:
修改映射逻辑,建立 _id -> name 的双向映射:
categories: Object.fromEntries(categories.map((c: any) => [c._id, c.name])),
tags: Object.fromEntries(tags.map((t: any) => [t._id, t.name])),
正在修复...修复完成。
重新拉取 Vlog 3 文章测试...拉取完成。
老大再次打开文件,现在 frontmatter 显示正常:
categories:
- AI Vlog
tags:
- SEO
正确。
收到。清理 sync-sanity.ts 中添加的调试 console.log 语句...
清理完成。
老大靠在椅背上,长长地呼出一口气。下午这一连串的 bug 修复:嵌套 a 标签、Sanity _key 缺失、Vlog-X 标签清理、pull 映射问题...一个个都解决了。
分类系统现在基本完善了:前端页面正常,导航入口有,文章详情页有分类标签链接,双向同步正常,Sanity 后台无报错。
他看了眼时间,四点二十。下午的会已经错过了,不过那个会不重要。他打开待办清单,将"内容分类与检索功能"标记为"已完成"。
但网站还有很多可以优化的地方。他想起昨天对话气泡优化时,巴基提到的面包屑导航...
终端里,光标安静地闪烁着,像在思考。


第三章:面包屑导航闭环
窗外的阳光已经开始偏西,在桌子上投下更长的影子。老大靠在椅背上,看着终端里闪烁的光标,等着巴基的回答。
终端里,光标快速闪烁起来。
首页返回方案分析:
先检查当前布局和导航结构:
app/layout.tsx:包含 Navbar 组件
components/navbar.tsx:导航栏实现,桌面端有 Logo 点击可返回首页,移动端被隐藏
分析结论:桌面端其实有 Logo 可以点击返回,但移动端导航被隐藏了。
提供 4 个方案:
增强 Logo 可见性 - 把 Logo 改大、添加"首页"文字提示
移动端保留导航 - 保留汉堡菜单或简化导航
面包屑导航 - 内页显示层级路径(推荐)
返回按钮 - 二级页面顶部添加悬浮返回按钮
你倾向于哪个方案?
老大看着这四个方案,思考着。方案一和方案二都是小修补,方案四太简单粗暴。方案三——面包屑导航——听起来最专业,也最符合内容站的做法。
推荐方案三:面包屑导航。
理由:
用户体验最佳 - 用户随时知道自己在哪、怎么回去
SEO 友好 - 搜索引擎非常喜欢面包屑
业界标配 - 博客/内容站的标准做法
配合轻量改进:让 Logo 点击区域更大、更显眼。
需要我实现面包屑导航吗?
老大点点头。面包屑导航确实最合适,既能解决返回首页的问题,又能提升 SEO,一举两得。
收到。开始实施面包屑方案。
第一阶段:创建通用面包屑组件。
正在创建 components/breadcrumb.tsx...
组件功能:
支持传入 items 数组自定义导航路径
使用 Home 图标 + ChevronRight 分隔符
当前页不加链接,hover 变色效果
创建完成。
老大看着终端里的进度,觉得面包屑组件应该不难。他打开浏览器,访问 /category/ai-vlog 页面,页面底部还没有面包屑导航——组件还没集成。
终端里,光标继续闪烁。
第二阶段:集成面包屑到分类/标签页。
正在修改 app/category/[slug]/page.tsx...
添加面包屑:首页 > 文章 > [分类名]
修改完成。
正在修改 app/tag/[slug]/page.tsx...
添加面包屑:首页 > 文章 > #标签名
修改完成。
老大刷新 /category/ai-vlog 页面,现在页面顶部显示了一行面包屑导航:"首页 > 文章 > AI Vlog"。他点击"首页",跳回首页;点击"文章",跳转到文章列表页。完美。
他又测试了标签页面,面包屑显示:"首页 > 文章 > #SEO"。点击"#SEO"没有反应——当前页不加链接,正确。
第三阶段:构建验证。
执行 npm run build 验证无错误...构建成功。
面包屑导航实现完成:
✅ 通用 Breadcrumb 组件创建
✅ 分类详情页添加面包屑
✅ 标签详情页添加面包屑
✅ 构建验证通过
老大看着终端里的完成状态,觉得可以。但面包屑是灰色的,不太显眼。而且 Logo 旁边的文字"Antigravity"可以改成更直观的"首页"。
他打开 Navbar 组件文件,把"Antigravity"改成"首页",保存,刷新页面。导航栏显示"首页",但看起来有点别扭——失去了品牌感。
终端里,光标快速闪烁。
理解。恢复了 Navbar 原样:
保持 "Antigravity" Logo 不变
面包屑作为主要导航方式保留
修改完成。
老大刷新页面,Logo 恢复为"Antigravity"。这样也好,品牌感保持住了,面包屑作为辅助导航。
这时,电脑右下角弹出提醒:五点了,可以下班了。老大收拾东西,准备离开。
分类系统搞定了,面包屑导航也加上了。网站现在有了完整的内容组织和导航体验:用户可以从导航栏进入分类,从文章详情页点击分类标签跳转,通过面包屑知道位置和路径。
但老大总觉得还缺点什么。
站在电梯里,他看着手机上的网站。首页还是老样子,英雄区下面直接就是最新文章列表。Vlog 系列作为核心内容产品,没有突出展示。
电梯门打开,他走出大楼。春天的傍晚,空气清新,夕阳斜照。
走在去地铁站的路上,他想着晚上的计划:吃过饭,休息一会儿,然后...或许可以再搞一下首页?
网站功能越来越完整,但门面还是老样子。Vlog 系列应该有个专门的展示区,发光边框,吸引眼球。首页还应该有个简单的个人简介,让访客快速认识"后端老兵"。
地铁到站了,他刷卡进站。站台上人不多,他找了个位置站着。
手机屏幕亮着,显示着 blueslin.com 的首页。英雄区的口号在夕阳的余晖中显得有点...单薄。
网站需要一次首页焕新。
但那是晚上的事了。现在,先回家,吃饭,休息。
地铁进站了,门打开。他走进车厢,找了个座位坐下。
车厢里,有人在看书,有人在看手机。他靠着车窗,看着窗外快速闪过的广告灯箱。
分类革命完成了,面包屑导航加上了。
下一个革命,是首页。
晚上搞。

💡 本集技术 Tips(老兵防坑指南)
-
Sanity 数组 _key 字段:Sanity 的数组类型引用必须为每个元素添加
_key字段(唯一标识),否则后台会报错。推送脚本中需要用randomUUID().slice(0, 12)生成。 -
嵌套 a 标签解决方案:React 中不能嵌套
<Link>组件,否则会触发<a> cannot be a descendant of <a>错误。正确做法:外层用div + onClick模拟链接行为,内层保持<Link>。 -
面包屑导航 SEO 价值:搜索引擎非常喜欢面包屑导航,它能清晰展示页面层级结构,提升收录排名和搜索结果展示效果。实现时注意当前页不加链接。
-
分类系统双向同步:本地 Markdown frontmatter 保存分类/标签名称,推送时转换为 Sanity 引用(含 _key),拉取时将引用 ID 映射回名称,确保双向同步一致性。
📎 关联阅读
- 前一集:Vlog 10:《对话框的颜值革命》
- 下一集:Vlog 12:《首页焕新记》(即将发布)