fix(docs): /docs 根路由 404 — 加 landing page 列出所有分区#290
Conversation
Header 导航栏 "文档 / Docs" 点进去是 /docs,但路由目录下只有 app/docs/[...slug]/page.tsx(catch-all 不匹配空 slug)和 layout.tsx, 没有东西匹配 /docs 本身,所以生产直接 404(x-matched-path: /_not-found)。 修法:新增 app/docs/page.tsx(server component),复用已有的 docs layout, 读 fumadocs source.pageTree.children 顶层分区渲染成 Cards 列表: - 不硬编码分区名,新增顶层目录自动出现在 landing - 卡片标题/描述读各分区 index.mdx frontmatter,没 index 的分区(jobs / all-projects)降级用目录名 + 兜底到子树第一个 page 的 url,保证不点空 - locale 从 cookie 读(zh/en),只切 H1/intro 两句话;卡片内容本身 已由 [...slug] 的 locale fallback 负责,这里不重复处理
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
为 /docs 根路由新增一个 landing page,解决导航栏直达 /docs 在生产环境返回 404 的问题,并在该页面动态列出 docs 顶层分区入口卡片。
Changes:
- 新增
app/docs/page.tsx作为/docs的 server component 路由,渲染分区卡片列表 - 从
source.pageTree.children生成卡片数据,并为无index的分区提供 fallback 跳转 URL - 基于 locale cookie 切换 landing 页的标题与简介文案,并补充页面 metadata
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| indexUrl ?? findFirstPageUrl(folder.children) ?? undefined; | ||
| if (!fallbackUrl) return null; | ||
| return { | ||
| title: asPlainText(folder.name), |
There was a problem hiding this comment.
Folder 类型分区卡片目前用的是 folder.name 作为标题(通常是目录名如 ai),而不是分区 index.mdx 的 frontmatter/title。现有 docs 里如 app/docs/ai/index.mdx 的 title 是“AI 知识库”,按现在实现 landing 会展示成“ai”,与 PR 目标(用 index frontmatter.title/description)不一致。建议优先使用 folder.index?.name(或等价的 index page 标题字段)作为 title,并在缺失 index 时再回退到 folder.name。
| title: asPlainText(folder.name), | |
| title: asPlainText(folder.index?.name ?? folder.name), |
| const tree = source.pageTree; | ||
|
|
||
| const cards = tree.children | ||
| .map(toSectionCard) | ||
| .filter((c): c is SectionCard => c !== null); |
There was a problem hiding this comment.
这里读取的是未处理过的 source.pageTree,但 docs 的 layout.tsx 会对 tree 做 pruneEmptyFolders(source.pageTree) 后再交给 DocsLayout。landing 用原始 tree 可能会把 layout 已经 prune 掉/提升成 page 的节点也展示出来,导致 landing 卡片与侧边栏结构不一致。建议复用同一份 prune 逻辑(例如将 pruneEmptyFolders 提到共享 util 并在这里也使用)。
| /** 把 pageTree 顶层 node 映射成 landing 卡片;遇到 separator / 孤立 page 就跳过 */ | ||
| function toSectionCard(node: PageTree.Node): SectionCard | null { | ||
| if (node.type === "separator") return null; | ||
| if (node.type === "page") { | ||
| // 顶层直接挂的文件(比如目录只有一个文件被 pruneEmptyFolders 提出来了) |
There was a problem hiding this comment.
注释“遇到 separator / 孤立 page 就跳过”与实际逻辑不一致:当前 node.type === "page" 会被映射成卡片而不是跳过。建议更新注释以匹配真实行为,避免后续维护者误解。
合并 #288 + #290 + app/docs/CommunityShare/Leetcode/index.mdx 里原先三份 各自实现的"列目录子节点"逻辑,改成一个 server component。 ## 为什么要合并 原本三处各自实现: - /docs 根路由(PR #290 draft)—— 读 pageTree.children - CommunityShare/index.mdx(PR #288 draft)—— 读 getPages() 过滤 path - CommunityShare/Leetcode/index.mdx —— 内联 MDX 里 source.getPages().filter().map() drift 问题:排序、英文过滤、fallback URL 三份逻辑各走各的;更严重的是 PR #288 里对"没 index.mdx 的子目录"硬拼 /docs/CommunityShare/<dir> 会 404 (Copilot CR 指出),和 PR #290 修 /docs 404 是同一个根因:Next [...slug] 不匹配空 slug,folder 没 index 就意味着 /docs/X 没 route。 ## <SectionIndex root?> - 走 source.pageTree(不是 getPages),fumadocs 已经把 folder+index 关系建好了,不用自己从扁平 page 列表反推 - root 接 "CommunityShare" / "CommunityShare/Leetcode" 这种相对路径, 不传就是从 pageTree 根开始(给 /docs landing 用) - URL 永不硬拼:folder 有 index 走 index.url;没 index 递归找子树第一个 page 的 url 作为 fallback(直接修掉 CR 那个 404 bug) - 英文翻译版(URL 末段 .en)过滤不进列表;语言切换仍由 [...slug] 的 cookie fallback 负责 - 统一 fumadocs <Cards>/<Card> 视觉 ## 本地验证 - /docs → 5 张卡片,全部 200 - /docs/CommunityShare → 8 张卡片,全部 200(包括原先会 404 的 Language/ Life/Personal-Study-Notes/RAG 四个没 index 的分类,现在点进去是子目录里 第一篇 page,不再死链) - /docs/CommunityShare/Leetcode → 49 张卡片,0 个 .en 泄漏 ## 取代关系 - 关闭 PR #288(CommunityShareIndex 专用实现,有 404 bug) - 关闭 PR #290(/docs landing 单独实现) - 本 PR 一并覆盖,继续承担解决 #110 的责任 Co-authored-by: LynPtl <194795025+LynPtl@users.noreply.github.com>
|
并入 #292: |
…(取代 #288 #290) (#292) * refactor(docs): 统一 /docs、CommunityShare、Leetcode 三处索引为 <SectionIndex> 合并 #288 + #290 + app/docs/CommunityShare/Leetcode/index.mdx 里原先三份 各自实现的"列目录子节点"逻辑,改成一个 server component。 ## 为什么要合并 原本三处各自实现: - /docs 根路由(PR #290 draft)—— 读 pageTree.children - CommunityShare/index.mdx(PR #288 draft)—— 读 getPages() 过滤 path - CommunityShare/Leetcode/index.mdx —— 内联 MDX 里 source.getPages().filter().map() drift 问题:排序、英文过滤、fallback URL 三份逻辑各走各的;更严重的是 PR #288 里对"没 index.mdx 的子目录"硬拼 /docs/CommunityShare/<dir> 会 404 (Copilot CR 指出),和 PR #290 修 /docs 404 是同一个根因:Next [...slug] 不匹配空 slug,folder 没 index 就意味着 /docs/X 没 route。 ## <SectionIndex root?> - 走 source.pageTree(不是 getPages),fumadocs 已经把 folder+index 关系建好了,不用自己从扁平 page 列表反推 - root 接 "CommunityShare" / "CommunityShare/Leetcode" 这种相对路径, 不传就是从 pageTree 根开始(给 /docs landing 用) - URL 永不硬拼:folder 有 index 走 index.url;没 index 递归找子树第一个 page 的 url 作为 fallback(直接修掉 CR 那个 404 bug) - 英文翻译版(URL 末段 .en)过滤不进列表;语言切换仍由 [...slug] 的 cookie fallback 负责 - 统一 fumadocs <Cards>/<Card> 视觉 ## 本地验证 - /docs → 5 张卡片,全部 200 - /docs/CommunityShare → 8 张卡片,全部 200(包括原先会 404 的 Language/ Life/Personal-Study-Notes/RAG 四个没 index 的分类,现在点进去是子目录里 第一篇 page,不再死链) - /docs/CommunityShare/Leetcode → 49 张卡片,0 个 .en 泄漏 ## 取代关系 - 关闭 PR #288(CommunityShareIndex 专用实现,有 404 bug) - 关闭 PR #290(/docs landing 单独实现) - 本 PR 一并覆盖,继续承担解决 #110 的责任 Co-authored-by: LynPtl <194795025+LynPtl@users.noreply.github.com> * docs(SectionIndex): 加大量中文注释说明 pageTree 心智模型 + 每步做什么 * fix(SectionIndex): 按 CR 补齐 locale 变体过滤 + 去掉注释里的 markdown Copilot 在 #292 提了 3 条要修的: 1) isEnglishVariant 只过滤 .en,没管 .zh —— 站点实际有 .zh.md(原文是 en 时的中文翻译), 重复链接会在索引里暴露。改成 isHideableLocaleVariant(url, canonicals):只有对应 canonical 存在时才隐藏,孤儿(只有 .en 或 .zh 单一形态的文档,共 35 + 7 篇)保留。 2) folder.index 如果本身是翻译版(理论上会有 index.en.mdx / index.zh.mdx),不能直接 当卡片 href,会暴露非 canonical URL。nodeToCard 里给 idxUrl 加同样的过滤,不合规时 退回 findFirstPageUrl。 3) folderSegmentName 注释写的"倒数第二段"但代码取的是最后一段,改掉注释。 另外按用户反馈清掉注释里的 markdown(**bold**、反引号等),代码注释又不会被渲染。 --------- Co-authored-by: LynPtl <194795025+LynPtl@users.noreply.github.com>
现象
Header 导航栏 "文档 / Docs" 直接指向 `/docs`,点进去生产 404:
```
$ curl -I https://involutionhell.com/docs
HTTP/2 404
x-matched-path: /_not-found
x-next-error-status: 404
```
根因
`app/docs/` 下当前只有两样东西:
`/docs` 本身没有任何 route 匹配 → 走 `not-found`。
修法
新增 `app/docs/page.tsx`(server component),复用 `app/docs/layout.tsx` 已经挂好的 DocsLayout(侧边栏 / copy tracking / view tracking 都自动继承),自己只负责渲染中间内容区:
本地验证
```
$ curl -s -o /tmp/docs.html -w "HTTP %{http_code}\n" http://localhost:3010/docs
HTTP 200
```
5 张卡片渲染:AI 知识库 / Computer Science / 群友分享 / Jobs / All projects。
Test plan