页面树与动态路由
完整文件清单
pages/[locale]/ 下 22 个文件,按职责分组:
入口与聚合
章节页
详情页
跳转
注意 /[locale]/game 不存在。useLayoutRouteMode 等 hook 的 prefetch 匹配里仍把它当作独立分支,但 pages/[locale]/game 实际没有对应文件——这是 GOTCHAS.md 第 21 条记录的「历史遗留匹配」。
受保护与 feed
getStaticPaths 行为
web/[id].tsx:paths从data/projects(按 locale 切)三组(web / game / early)展平。fallback: false。life/[slug].tsx:paths从data/life展平(gameData / travelData / otherData)。fallback: false。blog/[slug].tsx:paths从blog-index.json拉取 slug 列表(在外部内容仓库配置时)或回退到content/blog/init/的内置文章。fallback: 'blocking'让新增 slug 在被请求时实时生成(ISR)。
状态与布局上下文
详见 routes-and-proxy 之外的几个 context:
contexts/AppContext.tsx— 站级交互态与效果:loading 序列、power/battery/inversion、实时统计、首页打字机、column hover 状态。contexts/TransitionContext.tsx— 控制路由过渡动画。所有内部跳转必须用useTransition().navigateTo(url),不能用router.push()。支持setBackOverride()让 detail view 和 lightbox 拦截 BACK 行为。contexts/LayoutAnchorsContext.tsx— 注册 active scroll container。因为 layout 用锁定高度的内容容器,深链 scroll 必须打到那个容器而不是 document viewport。contexts/SiteAssetsContext.tsx— 提供 site-shell 资源(如favicon、og:image、avatar)的解析结果。
路由 loading 覆盖层
useRouteLoadingKind(router) 从「离开的路径」而不是「目标路径」决定 loading 变体:
home/content → blog detail:用右侧默认 overlay,左侧 HUD 仍可见blog detail → blog detail:用 standalone overlay,左侧 HUD 已隐藏
不能改成「按目标路径」判断——会破坏其中一种方向。这是 GOTCHAS.md 第 7 条。