ZHANG.LOG
Next.jsTypeScriptMDX

张的个人网站

发布于 2026-08-29阅读时间 15 分钟

Zhang(张)的,Agent 协作打造的个人作品集网站 —— 一名大学生开发者用于记录和分享个人 Agent 使用经历和经验的实操集合。它基于我对 Agent 能力的好奇与探索,在探索过程中点滴积累,汇集成了网站各部分设计,它源自“一个身为开发者怎能不打造一个个人网站”的想法,后把想法交由 Agent 加工、处理得到。全过程,我负责统筹设计开发,设计提示词,检查验收,优化交互体验,打磨细节;Agent 全程辅助配合完成任务,并接管全部代码开发。一起看看我与 Agent 协作实践流程。

技术选型

层技术
框架Next.js 16(App Router)
UIReact 19 + TypeScript
样式Tailwind CSS v4
动画motion(motion/react)
内容MDX + @next/mdx(mdxRs 编译器)
图标lucide-react

内容设计:目标定位与内容设计

核心说明:明确目标与定位,向 Agent 点明网站的核心定位,以及我对这个网站的功能需求,这样便在上下文中加入了终极目标说明,Agent 如有需求,可在每步后都对照总目标进行修正,微调。同时,可以使用 Harness 提供的 goal (目标模式),实现和上述提示词设计思路一样的效果。随后是主体内容设计,主要是 Agent 使用记录,包括编程,创作,自动化等场景,然后总结记录经验分享。再者便是浅浅介绍自己。Agent 瞄准目标设计多种方案给我拍板,不满意则可与其交谈微调方向,直至拍板实施。

内容系统设计:MDX 驱动的数据流引擎

内容引擎要支撑长期、增量、多形态的内容产出。本项目用同一个静态站点同时承担这两种角色,核心课题是——如何在单一路由下把两者统一,而不牺牲其中任何一方的体验。全站内容收敛在 content/ 目录的 MDX 文件里。构建前由 generate-content-data.js 把每个文件拆成三层,各司其职:

产物内容职责
content-data.jsonfrontmatter 元信息驱动首页、列表与"精选"
lib/generated/*.mdx剥离 frontmatter 的中文正文编译为正文组件
lib/generated/*.en.mdx剥离 frontmatter 的英文 sidecar 正文编译为英文正文组件
mdx-registry.tsslug → 中英文 Component 映射按语言取用正文组件,英文缺失时回退中文
TypeScript
import Practice0 from '@/lib/generated/practice/zhang.log.mdx';

export const practiceComponents: Record<string, ComponentType> = {
  'zhang.log': Practice0,
};

三层拆分的价值在于内容与结构的解耦:元数据与正文各自独立编译,正文组件化让每篇文章可被单独注册与替换——增删一篇内容,只需维护一个 MDX 文件。

内容渲染策略

与 Agent 讨论建议静态生成的确定性。元信息来自构建期静态数据,正文来自编译期注册组件,路由以 generateStaticParams 预生成。整站几乎没有客户端数据请求:首屏确定、构建产物可预期、部署无运行时依赖。这种"用构建确定性换取运行灵活性"的模式,与内容更新频率不高的个人站场景高度契合。

国际化

路径段驱动的词典 app/[lang] 用路径段承载语言,getDictionary(lang) 返回 UI 词典。文章与提示词采用同一思路:content/{collection}/{slug}.en.mdx 是中文主稿旁的英文 sidecar,global-agents.en.md 是全局提示词的英文版本。生成器只读取 sidecar 中需要翻译的元信息字段,日期、封面、标签等共享字段仍以主稿为准,并分别生成 blogComponentsEn / practiceComponentsEn 供英文正文使用。getDisplayTag 负责标签本地化。语言被建模为一个路由参数加一次查表动作,没有引入重型 i18n 框架,轻量且与静态渲染天然兼容。

结构设计

目录结构,经过与 Agent 多轮讨论与修订得出:

context
zhang.log/
├── app/                          # App Router 路由与页面
│   ├── [lang]/                   # 语言段(cn / en),所有页面按语言静态预渲染
│   │   ├── layout.tsx            # 根布局、字体、导航、页脚与全局 Provider
│   │   ├── not-found.tsx         # 语言段内 notFound() 的本地化 404
│   │   ├── [...rest]/page.tsx    # 未匹配路径进入 notFound(),交给语言段 404
│   │   ├── page.tsx              # 首页数据装配
│   │   ├── HomeClient.tsx        # 首页视觉、轨道图和客户端交互
│   │   ├── about/                # 关于页
│   │   │   ├── page.tsx
│   │   │   └── AboutClient.tsx
│   │   ├── agents/page.tsx       # 兼容入口:重定向到首页 #agent-experience
│   │   ├── blogs/                # 博客页面路由
│   │   │   ├── page.tsx
│   │   │   ├── BlogClient.tsx
│   │   │   └── [slug]/page.tsx   # 文章详情(generateStaticParams)
│   │   ├── practice/             # 实践列表页路由
│   │   │   ├── page.tsx
│   │   │   ├── PracticeClient.tsx
│   │   │   └── [slug]/page.tsx   # 实践详情(generateStaticParams)
│   │   └── openclaw/             # OpenClaw 网关文档页
│   │       ├── page.tsx
│   │       ├── OpenClawClient.tsx
│   │       └── sections/         # 蓝图、结构、快速开始、配置、经验、场景与维护
│   ├── globals.css               # 全局样式与 Tailwind v4 主题色
│   ├── mdx.d.ts                  # MDX 模块类型声明
│   └── icon.png                  # 站点图标
├── components/                   # 核心共享组件
│   ├── AgentExperience.tsx       # 首页 Agent 方法、工具与经验展示
│   ├── AutoHideScrollbar.tsx     # 滚动时显现、静止时隐藏的自定义滚动条
│   ├── BackToTop.tsx             # 回到顶部按钮
│   ├── CodeBlock.tsx             # 代码语言标签、复制与横向滚动
│   ├── Footer.tsx                # 全站页脚与社交入口
│   ├── ImageLightbox.tsx         # 图片灯箱
│   ├── ListFilters.tsx           # 列表搜索、筛选和排序控件
│   ├── Navbar.tsx                # 桌面 / 移动导航与语言切换
│   ├── NotFoundView.tsx          # notFound() 回退共用的 404 内容
│   ├── Pagination.tsx            # 列表分页
│   ├── ParallaxImage.tsx         # 图片视差与渐进加载封装
│   ├── ParallaxSection.tsx       # 页面区块视差
│   ├── PracticeIcon.tsx          # 实践图标映射
│   ├── PracticeTableOfContents.tsx # 长文目录:桌面侧栏 + 小屏抽屉
│   ├── ProgressiveImage.tsx      # 本地封面渐进加载
│   ├── SmoothScroll.tsx          # Lenis 惯性滚动
│   ├── useSectionScrollSpy.ts    # 章节滚动高亮
│   ├── WorkspaceFileMap.tsx      # OpenClaw Workspace 文件关系图
│   └── ZoomableImage.tsx         # 正文图片灯箱与缩放
├── content/                      # 内容源(MDX / Markdown,唯一内容入口)
│   ├── agents/                   # 全局 Agent 提示词(中文主稿 + 英文 sidecar)
│   ├── blog/                     # 博客文章(主稿 + .en.mdx sidecar)
│   ├── openclaw/workspace/       # OpenClaw 六份工作区 Markdown 源
│   └── practice/                 # 实践(主稿 + .en.mdx sidecar,受约束 frontmatter 驱动)
├── docs/                         # 项目规范
│   └── mdx-spec.md               # MDX 编写规范
├── lib/                          # 数据与业务逻辑
│   ├── agent-content.ts          # 首页 Agent 精选工具数据
│   ├── content.ts                # 内容读取接口(导入 content-data.json)
│   ├── i18n.ts                   # 中英文案(cnContent / enContent)
│   ├── i18n-context.tsx          # 共享组件的客户端语言上下文
│   ├── mdx-registry.ts           # 生成:中英文 MDX 正文静态导入注册表
│   ├── scenarios.ts              # 实践场景 key 的唯一来源
│   ├── tag-display.ts            # 标签展示语言映射
│   ├── utils.ts                  # cn() 工具(clsx + tailwind-merge)
│   ├── data/content-data.json    # 生成:内容元数据
│   └── generated/                # 生成:去除 frontmatter 的中英文 MDX 正文副本
├── scripts/generate-content-data.js # 生成 JSON、registry 与无 frontmatter 正文
├── public/images/                # 头像、站点图标、博客 / 实践封面与 OpenClaw 素材
├── README.md                     # 项目入口、开发流程与内容约定
├── DESIGN.md                     # 视觉设计系统规范(Google Stitch design.md 格式)
├── edgeone.json                  # EdgeOne 缓存与部署配置
├── AGENTS.md / CLAUDE.md         # 给编码 Agent 的行为准则
├── proxy.ts                      # 路由中间件(非语言路径重定向到 /cn)
├── mdx-components.tsx            # MDX 渲染组件映射
├── next.config.ts                # Next.js 配置(mdxRs、本地图片)
├── postcss.config.mjs
├── tsconfig.json / next-env.d.ts
└── package.json / package-lock.json

样式与交互设计

设计 DESIGN.md 以统一页面风格。DESIGN.md 是由 Google Stitch 团队开源的一套设计系统规范格式。用于向编码代理描述视觉标识的格式规范。它使代理能够持久、结构化地理解设计系统。通过编写一套网站视觉设计规则,来统一全站设计语言。以下摘要与仓库根目录的 DESIGN.md 同步维护;若两者出现差异,以根目录文件为准。本站视觉语言如下:

DESIGN
---
version: alpha
name: ZHANG.LOG
description: 暗色编辑式个人实践站——近黑底、纸白大字、细规则线与克制的龙虾橙状态强调。
colors:
  ink: "#050505"
  surface: "#0b0b0b"
  paper: "#f1f1ee"
  fog: "#9b9b96"
  rule: "#262624"
  signal: "#ff5a24"
  secondary: "#2dd4bf"
typography:
  sans:
    fontFamily: Geist
    roles: body, headings, controls
  mono:
    fontFamily: Geist Mono
    roles: metadata, indexes, paths, code
  display:
    fontFamily: Geist
    fontSize: clamp(3.2rem, 7.2vw, 6.35rem)
    fontWeight: 500
    lineHeight: 0.94
    letterSpacing: -0.07em
  body:
    fontSize: 1rem
    lineHeight: 1.75
  label:
    fontSize: 0.625rem
    lineHeight: 1.4
    letterSpacing: 0.12em
rounded:
  panel: 8px
  sheet: 16px
  stage: 32px
  pill: 9999px
spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
layout:
  contentMaxWidth: 1120px
  mobileGutter: 20px
  desktopGutter: 24px
  navHeight: 64px
  navHeightDesktop: 80px
components:
  navbar:
    backgroundColor: "rgba(5,5,5,0.88)"
    borderColor: "{colors.rule}"
    height: "{layout.navHeight}"
  button-primary:
    backgroundColor: "{colors.paper}"
    textColor: "{colors.ink}"
    rounded: "{rounded.pill}"
  button-secondary:
    backgroundColor: transparent
    borderColor: "{colors.rule}"
    rounded: "{rounded.pill}"
  index-row:
    borderColor: "{colors.rule}"
    backgroundColor: transparent
  code-block:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.paper}"
    rounded: "{rounded.panel}"
    typography: "{typography.mono}"
---

## Overview

ZHANG.LOG 是一份持续维护的个人实践日志,而不是套用作品集模板的营销页。视觉方向是“暗色编辑式工作台”:近黑画布承载纸白大字,细规则线组织信息,等宽字体标记时间、编号与路径,少量龙虾橙只在状态、强调和交互反馈中出现。

页面先讲正在做的事,再给出实践、方法、验证和文章。层级应来自留白、字号、字重和规则线,而不是大量玻璃卡片、渐变标题或装饰性图标。整体感觉应当冷静、直接、可检查,像一份被认真编排的工程记录。

首页用“想法 → Agent → 现实”的轨道图建立整站隐喻;实践与博客使用索引行而非同质卡片墙;详情页把长文、图片和目录组织成可持续阅读的坐标系。动效服务于叙事和反馈,不替代信息。

## Colors

- **Ink(#050505):** 页面与导航的主背景,也是纸白组件上的反白文字色。
- **Surface(#0b0b0b):** 代码块、媒体占位和信息面板的次级底色,与 Ink 只拉开一档。
- **Paper(#f1f1ee):** 主标题、关键正文、主按钮底色和当前导航态。避免使用刺眼的纯白。
- **Fog(#9b9b96):** 说明文字、元信息、未激活导航和次要操作。
- **Rule(#262624):** 分隔线、描边、输入框边界和低层级容器。结构主要靠线,不靠重阴影。
- **Signal(#ff5a24):** 错误、当前章节、编号、状态点和 hover 强调。它是定位色,不是大面积底色。
- **Secondary(#2dd4bf):** 极少量状态或校验节点;不得与 Signal 争抢主次。

颜色优先级固定为 Ink / Paper / Fog / Rule,Signal 只占很小面积。渐变仅用于抽象轨道、图片遮罩和场景化动效,不用于普通文字卡片。

## Typography

- **正文 Sans:** Geist。正文常用 16px / 1.75,长文在桌面可放大到 `lg:prose-lg`;描述性文字用 Fog。
- **标题 Sans:** 仍使用 Geist,以 `font-medium` 和紧凑字距建立层级。首页主标题使用 `clamp(3.2rem, 7.2vw, 6.35rem)`、`line-height: 0.94`、`letter-spacing: -0.07em`。
- **Mono:** Geist Mono。用于日期、序号、路径、代码、状态和章节编号;不用于长段正文。
- **Label:** 10–12px 等宽大写或中文小标签,字距约 `0.12em`–`0.16em`,承担“记录数据”的异质感。
- **长文:** 标题最高 6 个字号层级;正文段落默认首行缩进 2 字符,列表项、表格单元格不缩进。可用 `<Indent n={N}>` / `<NoIndent>` 逐段覆盖。
- **小屏字级:** 依靠 `clamp()` 和 `md:` / `lg:` 断点调整,不缩放根字号。正文表格与代码块在小屏降到 12px。

## Layout

- **内容宽度:** 主内容最大宽度 `1120px`,左右留白移动端 20px、`sm:` 起 24px;长文正文列再收窄,避免宽幅直排。
- **导航:** 固定顶栏高 64px,`sm:` 起 80px。桌面链接居中,语言切换与 OpenClaw 入口靠右;移动端使用汉堡菜单。
- **首页:** 主标题与说明采用不对称 12 栏布局;板块垂直间距以 `py-16 md:py-24` 为主,局部叙事区可扩展到 `py-20 md:py-32`。
- **列表:** 实践和博客以规则线分隔的索引行呈现,不使用统一圆角卡片。实践桌面为 4/8 分栏图文行,博客为 2/7/2/1 的日期、标题、阅读时间和箭头结构。
- **详情:** OpenClaw 与实践详情在 `lg:` 使用 8/4 分栏:左侧正文,右侧 sticky 导航与相关内容;列表与首页封面按 16:9 裁切,详情头图以 `fit="contain"` 完整显示。新源图优先使用 16:9;`zhang.log.png` 是既有兼容特例。
- **断点:** 小屏基础值优先,`md = 768px`,`lg = 1024px`。移动端验收以 `360×800`、DPR 2 为硬性下限。
- **间距:** 4px 基础刻度;常用 `gap-4 md:gap-6`、`p-4 md:p-6`、`pt-28 sm:pt-36 lg:pt-40`。

## Components

- **navbar:** 全宽近黑半透明栏,底部一条 Rule;滚动向下隐藏、向上恢复。当前项用 Paper 与 Signal 小点表示,不使用大型悬浮胶囊。
- **button-primary:** Paper 实底胶囊 + Ink 文字,用于“查看实践”等高优先级入口;hover 变亮,不使用橙色铺底。
- **button-secondary:** 透明底 + Rule 描边胶囊,用于次级入口;hover 只提高边框和文字层级。
- **index-row:** 项目、博客和归档的主要列表单元。以 `border-t border-rule` 分隔,hover 让标题、箭头和局部底纹向 Signal 过渡;触屏使用 `:active` 提供即时按压反馈。
- **article-prose:** 实践与博客详情共用。H2 带章节编号和底部分隔线,H3 使用 Signal 左线;正文最大可读宽度随详情分栏收敛。
- **longform-nav:** 桌面显示完整 sticky 目录;小屏右侧显示刻度入口,点击后拉起底部抽屉。目录通过 portal 挂到 `body`,避免视差容器改变 fixed 定位参照。
- **code-block:** Geist Mono、Surface 底、语言标签与复制按钮;长行横向滚动,不手工折行。触屏设备让复制按钮常显。
- **media:** 本地资源优先,封面使用渐进模糊加载,正文图片支持灯箱与缩放。图片替代文本必须描述内容,不写文件名。
- **not-found:** 语言段内的未知路径与不存在的内容 slug 共用标题、说明、首页 / 实践 / 博客入口,并沿用 Navbar、Footer 与同一套暗色设计令牌。

## Motion

- 滚动惯性由 Lenis 提供;章节跳转需要立即打断惯性滚动,并保留可回访的 hash 锚点。
- 首屏轨道图表达“想法 → Agent → 现实”,底部 CTA 可在指针悬停或键盘聚焦时展开工作台场景。
- hover 只做小位移、边框提亮或颜色过渡;触屏通过 `:active` / `data-pressed` 给出反馈。
- 所有装饰动效必须支持 `prefers-reduced-motion: reduce`。动画不得遮挡正文、阻塞点击或改变布局尺寸。

## Quality Bar

- `360×800`、DPR 2 下页面 `scrollWidth ≤ 360`;宽表和长代码只在自身容器内横向滚动。
- 桌面与移动端都必须验证导航、列表筛选、分页、详情跳转、目录锚点、图片灯箱和回到顶部。
- 站内链接必须指向存在的路由、语言段和锚点;站外链接不得为空,必须指向有效目标,并明确是否新开窗口。
- 所有可交互元素要有可见焦点、可读标签和键盘操作;外链新开窗口时使用安全的 `rel`。
- 发布前执行内容生成、类型检查与生产构建,并同时检查中文与英文路由是否存在 404 或错误回退。

## Do's and Don'ts

**Do**

- 先用规则线、留白和字级建立结构,再考虑是否真的需要容器或阴影。
- 用 Signal 标记当前态、编号、状态点和少量关键动作。
- 优先使用真实内容密度组织页面;列表、表格和代码应能直接扫描。
- 保持移动端基础尺寸,再用 `md:` / `lg:` 恢复桌面尺度。
- 每次修改 UI 后同时检查桌面和小屏,至少覆盖 `360×800`。

**Don't**

- 不要把 Signal 铺成大面积背景,也不要用多套高饱和色并置。
- 不要恢复已淘汰的 Playfair Display、Inter、JetBrains Mono 字体组合描述。
- 不要把每个板块都包装成玻璃卡片;编辑式页面以规则线和非对称布局为主。
- 不要给纯展示面板添加橙色光晕、箭头或 hover 抬升,制造可点击错觉。
- 不要用缩放根字号实现小屏适配,也不要让页面主体产生横向溢出。

设计规范落地后,站点又做了一轮小屏(小于 768px)打磨:间距、内边距与圆角以移动端为基准值,用 md: 断点恢复桌面尺度;表格与代码块在小屏降到 12px,宽表与长代码行只在各自容器内横向滚动;正文段落默认首行缩进 2 字符,需要时可逐段覆盖。长文目录在小屏收敛为右侧刻度条,点击展开底部抽屉;因为目录节点挂在 body 上,它不会被视差容器的 transform 影响定位。

设计语言统一后,提示 Agent 每完成一部分实现,便可调用 playwright MCP 提供的网页访问和网页截图等工具,通过视觉能力查看截图,对比实际实现与预期实现效果,来修正代码,以达到预期实现。同时 Agent 可以参考优秀网页作品截图来实时回调我们的网页呈现效果,以及组件优化等。如此,不断的人与人工智能双方共同提示,设计,审核,验收,最后完成网站呈现效果的开发。

其他流程

除了上面提到的设计、结构与交互打磨,整个开发过程还有一些贯穿始终的流程,它们保证了与 Agent 协作的产出质量。

调用 GitNexus

Agent 使用 GitNexus 看懂代码库

这个项目的代码量会让"直接改"变得有风险,GitNexus 在"理解"和"修改"之间补了一层上下文。它把代码库索引成知识图谱,再通过 CLI 和 MCP 把调用关系、依赖链、执行流程交给 Agent 查询。

  • 建立索引:node .gitnexus/run.cjs analyze,让项目结构、符号关系和执行流程进入可查询状态。
  • 理解代码:用 query 找涉及的执行流程、context 看某个符号的调用者与被调用者,代替在陌生代码里盲搜。
  • 评估影响:改一个函数前先跑 impact 看 upstream 依赖,判断直接调用者与风险范围;遇到 HIGH / CRITICAL 风险先停下确认。
  • 检查变更:改完用 detect_changes 核对影响范围有没有偏离预期,再做最终验收。git 提交前使用,作用非凡。

这些动作被写进了项目的 AGENTS.md / CLAUDE.md,形成强制习惯:编辑符号前必跑 impact,提交前后必跑 detect_changes,探索路径用 query 而不是 grep。

技能调用:工具的说明书

本项目用的是 gitnexus 系列技能:exploring、impact-analysis、debugging、refactoring、guide、cli,这些技能详细描述了 gitnexus 的使用技巧,Agent 可以高效使用工具。遇到符合技能触发场景的任务,先加载技能再动手,避免每一次都重新交代一遍上下文。

总结

本次网站开发,我主要负责管理、监控,而 Agent 则是任务的直接执行人。这次任务 Agent 表现出的是出色的编程,设计能力,而我则是全局统筹能力、 Prompt 设计能力和结果验收能力(测试能力)。总之,Agent 的出现,使得人在编程场景的身份正在由编码者转向管理者。人只需在统筹阶段、任务制定阶段、关键走向定夺阶段和最后的验收阶段出手,其余交给长出手脚的 AI —— Agent 来完成。

本次实践仓库链接:Y-King666/zhang.log