2026-07-07-blog-list-page-redesign
博客列表页样式优化 Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 把 /blog 列表页和 /blog/tags/* 标签列表页的文章条目从"标题超大、信息稀疏"的默认 Docusaurus 样式,改造成紧凑的列表卡片样式(小标题、单行 meta、2 行摘要裁剪、可选缩略图),文章详情页视觉保持不变。
Architecture: swizzle(复制并改写)Docusaurus 内置的 BlogPostItem 组件到 src/theme/BlogPostItem/,按已有的 isBlogPostPage prop 分叉渲染:true 时完全复用原有详情页渲染逻辑(零视觉变化),false 时使用新的紧凑列表布局。摘要文字直接复用 Docusaurus 内置的 metadata.description(frontMatter.description || 自动摘要),不需要额外的摘要提取逻辑。同时给 4 篇正文里已有配图的旧文章补充 image frontmatter 字段,使其在列表中展示缩略图。
Tech Stack: Docusaurus 2.0.0-alpha.64(@docusaurus/theme-classic 提供的 BlogPostItem/BlogListPage/BlogTagsPostsPage 复用同一个 @theme/BlogPostItem 别名)、React 16.13.1 + TypeScript 4.0.2(strict 模式)、CSS Modules、clsx。
Global Constraints
- 所有新页面/组件文件使用
.tsx扩展名(CLAUDE.md 项目约定)。 - 样式使用 CSS Modules,条件类名用
clsx,不写内联样式(CLAUDE.md 项目约定)。 tsconfig.json开启strict: true(含strictNullChecks),但noImplicitAny: false;组件 props 需要显式类型定义。- 本仓库没有配置任何自动化测试框架(
package.json中无 jest/testing-library),验证手段为:tsc类型检查 +yarn build生产构建 + 本地yarn start手动浏览器验证(CLAUDE.md:前端改动必须在浏览器里跑一遍再算完成)。 - 不改动
BlogListPage、BlogPostPaginator、构建/部署流程(scripts/pre-build.js、GitHub Actions)。 - 文章详情页(
isBlogPostPage=true)视觉必须与改动前完全一致:标题字号、日期行、头像信息块、正文、Tags/Read More footer 均不能变。
Task 1: 给 4 篇旧文章补充 image frontmatter
Files:
- Modify:
blog/2017-12-31-tech-overview.md - Modify:
blog/2019-12-19-996.md - Modify:
blog/2020-11-13-vray.md - Modify:
blog/2020-12-31-year-summary.md
Interfaces:
Produces: 这 4 篇文章的 frontmatter 新增
image: <url>字段,供 Task 2 的BlogPostItem通过frontMatter.image读取并在列表页渲染缩略图。Step 1: 给
blog/2017-12-31-tech-overview.md加image字段
当前文件开头:
改为(在 author_image_url 后新增一行 image 字段,值取自该文章正文里已有的 <img src="...">):
- Step 2: 给
blog/2019-12-19-996.md加image字段
当前文件开头:
改为:
- Step 3: 给
blog/2020-11-13-vray.md加image字段
当前文件开头:
改为:
- Step 4: 给
blog/2020-12-31-year-summary.md加image字段
当前文件开头:
改为:
- Step 5: 核对 4 个文件都改对了
Run: grep -n "^image:" blog/2017-12-31-tech-overview.md blog/2019-12-19-996.md blog/2020-11-13-vray.md blog/2020-12-31-year-summary.md
Expected: 4 行输出,每个文件各一行 image: https://...,地址与上面 Step 1-4 一一对应。
- Step 6: Commit
Task 2: swizzle BlogPostItem,实现列表页紧凑布局
Files:
- Create:
src/theme/BlogPostItem/styles.module.css - Create:
src/theme/BlogPostItem/index.tsx - Test: 无自动化测试(本仓库无测试框架),用
tsc --noEmit、yarn build、yarn start手动浏览器验证代替。
Interfaces:
Consumes: Task 1 产出的 4 篇文章的
frontMatter.image字段;Docusaurus 运行时通过@theme/BlogPostItem别名自动优先加载src/theme/BlogPostItem/index.tsx(无需额外注册)。Produces: 默认导出的 React 组件
BlogPostItem(props: Props),Props包含children: React.ReactNode、frontMatter: FrontMatter、metadata: Metadata、truncated?: boolean、isBlogPostPage?: boolean;被BlogListPage、BlogPostPage、BlogTagsPostsPage(均来自@docusaurus/theme-classic,本次不改动)按原有方式调用。Step 1: 创建
src/theme/BlogPostItem/styles.module.css
- Step 2: 创建
src/theme/BlogPostItem/index.tsx
- Step 3: 类型检查
Run: npx tsc --noEmit
Expected: 无报错退出(exit code 0)。如果报 @mdx-js/react、@docusaurus/Head 等模块找不到类型,检查是否遗漏了原组件里的某个 import——不要新增依赖,这些模块的类型声明已经在 node_modules/@docusaurus/module-type-aliases 里全局声明过,同目录其它 src/theme/* 文件已经在用。
- Step 4: 生产构建
Run: yarn build
Expected: 构建成功退出(exit code 0),输出中出现 Client success / 生成 build/blog/index.html 等页面,没有 BlogPostItem 相关的 webpack/TS 报错。
- Step 5: 本地浏览器验证
Run: yarn start(默认监听 http://localhost:3000)
打开浏览器手动检查以下几点,逐条确认:
/blog列表页:每条目标题不超过 2 行、明显小于原来的超大标题;标题下方一行展示"头像 + 作者 + 日期 + 阅读时长",标签靠右显示(最多 4 个);摘要不超过 2 行。/blog列表页中 2026-07-06、2020-12-31、2019-12-19、2020-11-13、2017-12-31 这几篇(对应 Task 1 加了image的 4 篇 + 补充确认其余无图文章)——4 篇旧文章右侧应显示缩略图,其余文章不显示缩略图也不留空白。- 任意打开一篇文章详情页(如
/blog/2026/07/06/fshareim-product-showcase或站点实际生成的 slug),确认标题大小、头像信息块、正文、Tags、Read More 与改动前一致(可以用git stash临时还原对比,或凭记忆核对无明显变化)。 /blog/tags/(标签总览)下任选一个标签进入/blog/tags/<tag>,确认该列表页也是紧凑布局。- 把浏览器窗口缩到 640px 以下宽度,确认缩略图列隐藏、文字区域占满整行,没有布局错乱或横向滚动条。
确认以上 5 点都符合预期后,Ctrl+C 停掉 yarn start。
- Step 6: Commit