yiming-next 是这个站点从 WordPress 迁出后的新工程。技术栈是 Astro 5 + Node.js SSR standalone,内容全部以文件形式存储,没有数据库。内容仓如今是一个独立的 git 仓库,与应用代码分离:应用通过 CONTENT_ROOT 读取它,本地检出里 content 只是一个指向它的符号链接,src/lib/paths.ts 的 contentPath() 是访问内容的唯一入口。
这篇是工程全景的活文档,会随站点演进更新。下面写的是当前(2026-06)的真实状态,和首版相比改动不少。
内容层
文章和页面已经合一:所有条目都是 content/entries/*.md,不再分 posts/ 与 pages/。每条 frontmatter 里有一个数字 id 作为唯一真相,规范 URL 由它派生为 /?p=${id};其余字段含标题、摘要、可见性(public / private / password_protected)、分类、标签、封面等。
- 音乐(
content/music/playlist.json):全局播放器的曲目元数据。正文里的[music_player]短代码现在自描述、直接渲染,不再维护单独的注册表。 - 分类 / 标签(
content/taxonomy/):支撑分类和标签归档。 - 评论(
content/interaction/comments/):每篇文章一个 JSON 文件,含嵌套回复树。 - 主人长期记忆(
content/interaction/agent-memory/):每条记忆一个 Markdown 文件,仅 Agent Fox 在主人模式下使用(见下文)。 - 图片:不再使用独立的画廊 JSON,统一为正文内的纯 Markdown 图片;连续多图自动成组并套用通用 lightbox。
内容加载走 src/lib/content/load.ts,按可见性分公开和认证两条路径。Markdown 渲染管线(src/lib/content/render.ts)依次处理:WordPress 残留 HTML 区块转原生 Markdown、GFM 渲染、目录生成、HTML 清洗、LaTeX 数学公式、Mermaid 图、Shiki 代码高亮(nord 主题)、隐私遮罩展开、旧信纸体日记卡片。
页面路由
URL 方案保留了 WordPress 的查询参数习惯,但规范 URL 现在统一收敛为 /?p=N(不再用 /?page_id=)。其余入口(/?cat=、/?tag=、/?m=、/?s=)都在 index.astro 分发。同时也有语义路径:
/posts/文章列表,/posts/[slug]/文章单页/archive/和/archive/[year]/年份归档/categories/[slug]/和/tags/[slug]/分类/标签归档/search/站内搜索,/about/关于页面/feed.xml、/sitemap.xml、/search-index.json公开数据接口
[...legacy].astro 作为兜底路由处理未知路径。早期那套基于 url-inventory.yaml 迁移清单的重定向已退役,改由 src/lib/url-contract/ 的解析器收敛到规范 /?p=N。
全局运行时
前端运行时(src/components/runtime/SiteRuntime.astro + site-runtime.ts)如今精简为挂载 Agent Fox 与一组常驻交互:
- 全局音乐播放器:
Audio元素在页面导航中保持不中断,状态通过localStorage持久化,支持进度、音量、播放模式控制。 - 阅读进度条 + 文章目录:目录自动从标题生成、可折叠,滚动时高亮当前章节。
- 主题切换:亮色/暗色模式由 CSS 变量驱动;强调色统一为 Rosé Pine 的 pine 色系。
Agent Fox AI 助手
Agent Fox(src/components/agent/AgentFox.astro)通过 /api/agent/stream 提供 SSE 流式 AI 对话。关键设计点:
- 双模式:访客只检索公开内容;登录主人(密码 + TOTP 二次验证)获得完整站点上下文与「主人」人格。
- 工具集(13 个):
keyword_search、semantic_search、hybrid_search、get_post_chunk、comment_query、list_archives、list_taxonomy_terms、analyze_image、site_insight、recommend_content、manage_post(新建/编辑文章,仅主人)、manage_memory(长期记忆,仅主人)、agent_self_knowledge。 - 持久化陪伴:会话 id 与对话记录存
localStorage,跨刷新续聊;当前页面、浏览/点击轨迹与时间戳随消息尾部注入(稳定前缀不变,对 KV 缓存友好)。 - 主人长期记忆:仿 Claude Code 的「索引 + 渐进式披露」——平时只把每条记忆的简短钩子注入对话,完整正文按需展开;每条记忆是内容仓里的独立文件,owner-only,不进向量、访客不可见。它让小狐能跨会话记住主人的长期约定(如日常打卡提醒)并主动跟进。
- 两种停靠态:悬浮弹窗(Cmd/Ctrl+K 唤起)与侧栏「页边批注」之间可互切,共享同一份对话。
- 数据回调:
/api/agent/data/[kind]与/api/agent/data/[...path]提供文章、批量内容、分类、评论、记忆等 JSON 接口;私密数据需同时满足服务端 api-key 与已登录主人两个条件。 - 语义检索:走独立的向量服务(正文、摘要、评论分别建向量),站点侧负责生成与同步。
评论系统
评论提交端点为 /api/comments,提交时需通过算术验证码(HMAC 签名)。评论存储在 content/interaction/comments/posts/ 下,支持嵌套回复和树形渲染。旧的 WordPress REST 评论路由已退役。
登录与隐私
- 登录:密码 + TOTP 动态码二次验证(
src/lib/auth/);登录态用签名 cookie 维持,是判定「主人」身份的唯一可信来源——在服务端校验,浏览器无法伪造。 - 可见性:
public/private/password_protected;私密内容既不进向量,也不对访客和未登录者渲染。 - 遮罩:行内与区块统一的
<span class="ink-mask" role="img" aria-label="此处有隐藏内容" title="登录后可见">█</span>机制——访客看到墨条或「🔒 此处隐藏 N 字」占位,登录主人看到原文;公开面只暴露长度、不泄露内容。隐私过滤(src/lib/privacy/policy.ts)对公开渲染与 AI 数据回调一致生效。
其他模块
- OSS 图片代理:
/api/media/oss-image代理阿里云 OSS 图片,设置防盗链 referer 并附加长期缓存头;体积较大的静态资源都走 OSS,不塞进仓库。 - 健康检查:
/api/health,供外部监控和部署验证。 - 旧站兼容收敛:仍保留少量
/wp-json/agent-fox/*与/api/wp-ajax兼容动作,其余 WordPress 路由(评论、插件资源等)一律返回 410。整体方向是持续摆脱 WordPress 的迁移间接层。
部署
npm run build(typecheck + astro build)产出 dist/,由 systemd 服务 fanyiming.life 跑 Node standalone 入口;内容仓与应用仓彼此独立,文章改动只要在内容仓提交即可生效。
有话这里说 ↓