Log Detail

personal-homepage Git 变更总结

basil/personal-homepage 本次共 11 个提交,范围 1ab1717e..df4afe8a。

2026/05/06 basil/personal-homepage commit: 1ab1717e..df4afe8a

git-summarypersonal-homepage

basil/personal-homepage(personal-homepage)

本次范围

这 11 个 commit 完成了一次定位上的转向:从“等着别人往里写数据的静态站点”变成了构建时主动向外拉数据的静态站点 + 数据同步层。具体围绕三条线展开——打通 Gitea / Seafile 的数据拉取、把前端数据加载全切到生成产物上、以及让整套东西能被 AstrBot 可靠地触发和 Docker 化部署。

变更概要

1. 定位明确:静态站点 + 构建时数据同步层

一开始这个项目只是把自己当成一个摆静态页面的壳,数据从哪儿来并不关心。但实际跑起来才发现,如果让外部系统直接往 homepage 仓库里写文件,耦合会越来越重,权限和安全边界也会变模糊。

所以把心一横,角色反过来:站点本身在构建阶段主动去 Gitea / Seafile 拉数据,清洗完生成本地 JSON,再交给 Astro 渲染。运行时对外依然是纯静态页面,这一点从头到尾没变。REQUIREMENTS.md 和 TODO.md 都重写了大段描述来锚定这个新定位。

2. 打通 Gitea 和 Seafile 的数据管道

这是本轮改动量最大的部分。新写了 scripts/fetch-gitea.tsscripts/fetch-seafile.ts,分别负责:

  • 根据种子项目列表从 Gitea 拉 commit 活动数据(天数、每日上限等都可配);
  • 从 Seafile 拉分享资源的下载信息,再嵌回项目数据里。

这里有个背景值得提:log 类内容其实是 AstrBot 写到它自己目录下的,持久化保存是 AstrBot 的正常需求,只不过它把持久化目录放在了 homepage 能读到的位置。所以对 homepage 来说,构建时去读这个目录就行了。而仓库信息则不可能等着 Gitea 定时往 homepage 推送,必须是 homepage 主动去拉——这也是“主动拉取”这个方向定下来之后最自然的落地方式。

前端层也对应新建了 src/data/loaders.ts,封装了读取 generated JSON 的逻辑。index、projects、GiteaActivity 这些组件不再直接 import 静态 JSON,而是统一走 loader,数据源头从此只来自同步产出的 generated 目录。

3. 数据质量:Zod Schema 校验 + 同步元数据

同步脚本动不动就大几百行,中间哪个字段拼错了或者 API 返回结构变了,不出 Schema 校验的话只会在渲染时炸成一片空白,排查起来很痛苦。于是引入 zod,在 sync-content.ts 里给 projects、shares、gitea activity 都加了校验层,生成数据之前先验一遍,不合格直接毙掉,比事后修锅强得多。

另外给 GiteaActivity 组件接了一个 SyncMeta,把同步时间、数据来源之类的元信息展示出来,算是给站点维护者留了一扇观察窗。

4. 标准化重建入口,供 AstrBot 可靠调用

“AstrBot 每天定时触发一次同步 + 重建”——这个目标在 TODO 里躺了很久,现在落地成了 scripts/rebuild.ts。它不只是简单把 content:syncbuild 串起来,而是定义了标准化退出码(SYNC_FAILED=10 之类),让外部调用方能靠 exit code 判断是同步挂了还是构建挂了,方便做针对性告警或重试。

配套写了 docs/rebuild-trigger-spec.md,把这个入口的契约说清楚,AstrBot 或者 cron 照方抓药就行。

5. Docker 化部署 + 环境变量驱动 URL

从裸跑命令到能一把 docker compose up 是必要的跨越。新增了 Dockerfiledocker-compose.yml.dockerignore,并顺手把站点 URL、Gitea / GitHub 地址这些以前硬编码在 astro.config.mjs 里的东西全改成了环境变量(PUBLIC_SITE_URLPUBLIC_GITEA_URLPUBLIC_GITHUB_URL 等),通过 loadEnv 和 Docker ARG 注入。目的很简单:一次镜像,多环境可配,不因为换个域名就得改代码重新打镜像。

6. 文档补坑

  • 补了 README.md,让路人能三分钟内看懂这个仓库是干嘛的、怎么跑起来;
  • 补了 docs/content-sync-guide.md,把环境变量配置、数据源映射这些容易踩坑的地方都写明了;
  • TODO.md 里积压的已完成项终于划掉了一片。

7. 一点早期基础

最开始的 commit 还包含了一个 .codex/skills/ui-ux-pro-max/ 的东西,看描述是 UI/UX 设计辅助的智能参考库,算是另一个维度的基建种子。

关键决策与权衡

  • 全量同步 vs 增量同步:目前每次 rebuild 都会全量拉数据。以当前数据体量来说,这点资源消耗完全可以接受,而一旦引入“对比 hash / diff 来决定是否跳过构建”的机制,复杂度会显著上升——要处理缓存状态、上次同步文件的位置、部分数据变更的边界情况等等。所以现阶段选择先保持简单可靠,这条路未来数据量真的上去了再走也不迟,TODO 里已留了条目。

  • 错误信号标准化:rebuild 的 exit code 设计没有停留在简单的 0 和 1,而是细分了几种失败类型。这是为 AstrBot 那边的集成实打实考虑的——否则 AstrBot 触发完只知道“挂了”,完全不知道为什么挂。

  • 环境隔离:敏感信息(Token 之类)走 .env 不入仓,公开信息(URL 类)走构建参数注入,这两条线分得很清。代价是 Docker 构建时用户需要理解 ARG 的传法,有一点小门槛,但在文档里补了说明之后应该可以消化。

后续关注点

  • API 可用性依赖:主动拉取意味着 Gitea / Seafile 一旦挂掉或限流,构建就直接受影响。目前 SEAFILE_REQUEST_TIMEOUT_MS 设了 15 秒超时,但限流重试策略在代码里还没出现;
  • 同步失败时的降级:如果同步脚本挂了,站点构建会不会 fallback 到上一次生成的 JSON,还是直接裸奔——这个行为在代码里还不明确,是潜在风险点;
  • AstrBot 联调验证:rebuild 入口的规范已经有了,但实际 AstrBot 触发后的结果反馈链路还需要跑一遍真实集成测试来闭环。