Skip to content

Latest commit

 

History

History
207 lines (139 loc) · 14.9 KB

development.md

File metadata and controls

207 lines (139 loc) · 14.9 KB

开发与部署指南

从这里完成本地运行、个性化配置、内容维护与部署。页面规则见 站点与页面,改代码前先查 架构与模块边界。本文中的源码路径均相对仓库根目录。

本地运行 · 个性化 · 内容维护 · 外部服务 · 部署 · 检查与验收

本地运行

需要 Node.js 22.12 或更高版本,推荐与 CI 一致的 Node.js 24;包管理器为 package.json 声明的 pnpm 12.9.1。完整测试还需要 Python 3,发布预检会通过它调用已安装的 Astro 解析器。

pnpm install
pnpm dev --open

以终端日志中的实际 Local 地址为准,端口被占用时 Astro 会选其它端口。复用服务前核对进程的工作目录属于当前仓库/worktree,例如 lsof -a -p <pid> -d cwd。

模式 能验证什么 边界
pnpm dev 内容与组件热更新、草稿网页,以及本地 /api/lastfm、/api/playlists、/api/screen-time 搜索使用模拟数据;RSS 仍排除草稿
pnpm build 生产页面、图片资源、字体子集、Pagefind 索引及正文检查 不查询运行时接口,不启动网站服务
pnpm preview 最近一次 dist/ 的静态页面与真实搜索 不提供上述三个本地接口;不反映构建后的源码修改

Markdown 插件修改后若 dev 仍输出旧结构,用 pnpm dev --force 清内容缓存;普通刷新不会重新编译缓存的 Markdown。生产构建命令已带 --force。

个性化配置

先替换身份、内容和外部服务,再调整布局。不要把演示站的账号当成自己的配置。

要改什么 入口 注意事项
站名、域名、语言、默认分享图与部署 base src/config.ts → SITE 换域名/base/文章 slug 会影响永久地址、RSS 身份与评论关联,见 SEO 与订阅
顶栏入口、仓库 GitHub 与工具顺序 src/config.ts → UI 顶栏 GitHub 是仓库地址;个人主页属于 AUTHOR_LINKS
更多菜单中的关于、项目、友链、简历、相册、访问统计 src/config.ts → MORE_LINKS 相册和统计看板是外部站点,不由本项目生成
首页社交入口 src/config.ts → AUTHOR_LINKS 关于正文里的联系方式独立维护
作者展示名 src/config.ts → AUTHOR_DISPLAY_NAME 同时用于首页名字、页脚署名和文章版权卡
首页 INTJ、名言 src/components/blog/BlogProfile.astro 品牌文案在 src/components/nav/NavBar.astro,不随 SITE.title 自动同步
头像、图标、默认 OG 图 public/avatar.webp、public/ 及 SITE.socialImage 正文配图放 src/content/,不放这里
关于介绍 src/content/about/about.md 只有一个正文入口,不自动生成页签
友链申请模板 src/components/views/FriendsApplyPanel.astro → friendInfo 与 SITE 独立,需同步替换模板中的个人信息
页脚备案 src/components/base/Footer.astro 署名读 AUTHOR_DISPLAY_NAME;替换演示站备案,或按自己的站点情况移除
TOC、搜索、Oneko 开关 src/config.ts → FEATURES Oneko 皮肤与访客隐藏见 像素猫设计
拾趣菜单图标 src/config.ts → INTEREST_ICONS 键为分类文件名,不含扩展名;未配即纯文字菜单
点缀配色预设 src/utils/accent-palette.js 亮暗主题与点缀独立,预设首项为默认

样式文件分工与首屏加载方式见 架构设计。跨页壳层在 public/shell.css,全局变量与目录在 src/styles/main.css,正文组件在 prose.css,Markdown 排版在 markdown.css;局部组件样式仍由组件自己维护。

内容维护

完整字段以 src/content/schema.ts 为准,集合扫描范围以 src/content.config.ts 为准。

内容 维护位置 发布方式
博客 src/content/blogs/**/*.{md,mdx} 生产排除 draft: true;文件路径/slug 决定地址;pubDate 必填,lastModDate 可选取,不填时文章页「更新于」与发布日一致
文章封面 src/content/blogs/_title-images/,用 titleImage、titleImageAlt 引用 配置封面时必须有 alt
正文图片、音视频、绘图源 文章同目录或子目录 Markdown 使用相对路径;处理方式见 正文与媒体
项目 src/content/projects/data.json 按原始 category 分组
友链 src/content/friends/data.json category 为推荐或双向,组内按 order/名称排序
拾趣分类 src/content/interests/<id>.md 或 .mdx 顶层文件自动生成子页、入口和菜单;无草稿开关
首页近期书影游 自动取 src/data/media/items.json 的待看条目 无需单独维护
旅行/日历 src/content/trips/<id>/、src/content/calendar/<id>/entry.md 旅行用 pnpm trips:import 生成,日历写 Markdown;规则见 旅行与日历

新博客的最小起点:

---
title: 我的第一篇文章
pubDate: 2026-10-21
category: 技术
tags: [Astro]
draft: true
---

## 从这里开始

正文。

示例日期需替换为实际发布日期。博客 category 是必填的非空原值,新分类随已发布内容自动进入菜单。归档会为新分类领取配色并更新 src/data/blog-category-colors.json,把记录与文章一起提交。领取、占位和配色耗尽的规则见 归档。

新增拾趣分类只需在顶层放文件并填写非空 title、description 和非负整数 order,不改路由或导航数组。配图子目录不生成分类;同名子目录里的 Markdown 是该分类的页签。

作者操作与 AI 内容维护使用仓库内可独立安装的 内容发布 skill。将整个 blog-content-publisher-skill/ 复制到 Agent 的 skills 目录,保留 SKILL.md、脚本等依赖;可以直接提出“发博客”“新增拾趣分类”“换封面”“加友链”。skill 负责内容与配置,新博客在未明确发布时保留草稿;提交、推送和部署需有用户授权。

公式写 $…$ 或独立行 $$,不使用 \(...\)/\[...\]。复杂排版、卡片日期和媒体参数见 正文与媒体,可运行示例及完整可复制语法见 正文样式指南文章。

外部服务

Last.fm

首页「近期在听」在访问时从 /api/lastfm(封面墙)与 /api/lastfm-now(正在播放与最近播放)获取,仓库不存听歌快照。Vercel Production 与 Preview 环境均需配置 LASTFM_API_KEY;可选 LASTFM_USER 覆盖默认账户。本地将同名变量放在被忽略的 .env,由 dev 中间件调用同一个接口处理函数。

LASTFM_API_KEY=你的_API_Key
LASTFM_USER=你的_Lastfm_用户名

LASTFM_USER 环境变量仅覆盖接口查询账户。首页标题和无脚本说明中的主页链接在构建时读取 src/utils/lastfm.mjs 的 LASTFM_USER 常量;换成自己的账户时还需同步修改该常量并重新构建,避免听歌数据与主页链接指向不同用户。

缺密钥时接口返回 503,页面显示失败说明;不影响静态博客的构建。缺封面时由网易云搜索补齐,不需要额外凭据。接口缓存、封面回退、空数据与取消请求语义见 Last.fm 设计。密钥只在服务端使用,不写入源码或公开配置。

ActivityWatch 屏幕时间

首页屏幕时间在访问时从 /api/screen-time 获取,仓库不存快照。可选:在 macOS 或 Windows 上安装本机采集程序,每小时读取 ActivityWatch 的七日聚合结果,覆盖写入 Vercel Blob 的一个固定对象。不安装不影响构建,首页这一块只是拿不到数据。

Vercel 项目需连接一个 Public 的 Blob 存储。连接后平台注入 BLOB_STORE_ID(网站读取用,不涉密)。BLOB_READ_WRITE_TOKEN 只在安装采集程序时交给这台电脑,存进系统凭据库,不留在仓库。访问模式创建后不能修改,建成 Private 时接口会一直返回 502。

pnpm install
BLOB_READ_WRITE_TOKEN='从 Dashboard 复制' node scripts/install-screen-time.mjs

装完后每小时任务不再读取仓库,移动或删除仓库不会停止采集。换 Node、或快照格式变了,在仓库里重跑同一条命令。pnpm dev 读的是本机应用目录里的快照,不是仓库文件。状态码、路径、Windows 任务与卸载见 屏幕时间设计。

Giscus 评论

在自己的公开 GitHub 仓库启用 Discussions 并安装 Giscus App,用生成的仓库和分类信息替换 src/config.ts 的 GISCUS。评论出现在博客文章、友链页和全部拾趣分类子页,访客用 GitHub 登录后留言。

关联键为带尾斜杠的规范 pathname,本地与正式站的同一路径会使用同一讨论。修改 slug 或 base 需要处理旧讨论关联,本站不自动迁移。加载、主题和 OAuth 边界见 评论契约 与 实现边界。

Umami 与 Oneko

Umami 脚本位于 src/components/base/Head.astro;二次部署时更换或移除演示站的统计配置,MORE_LINKS 里的公开看板入口也需对应修改。脚本只加载一份,不在 astro:page-load 手动重复上报。

Oneko 使用外部托管脚本,开关与皮肤配置在 FEATURES.oneko。页脚可隐藏,减少动态时隐藏;详情和许可见 Oneko 设计。

部署

生产构建输出 dist/,postbuild 自动生成 Pagefind 索引、清理默认 UI 文件并检查正文是否成功渲染。dist/、public/_media/ 等派生产物不提交。

Vercel

仓库的 vercel.json 使用 framework: null(Other)、buildCommand: pnpm build、outputDirectory: dist,以同时提供静态页面和根目录 api/ 函数(听歌、歌单、屏幕时间)。保留这套配置;直接改用 Astro 框架预设可能导致这些接口返回 404。屏幕时间还需要在项目的 Storage 中连接一个 Blob 存储。

部署前核实 SITE.website/SITE.base、Giscus、统计及 Last.fm 账户。不要把 /blogs/ 重定向到首页,它承载文章列表和分类筛选。

其它静态平台

静态页面可从 dist/ 托管;听歌、歌单与屏幕时间接口需要自行适配平台函数或独立服务,单独托管静态文件不能提供它们。子路径部署先配置 SITE.base 并验证文章、资源、canonical、RSS 和评论路径;手写 /avatar.webp 等根路径引用时也需包含实际 base。

发布后核实页面、搜索、RSS、评论和所启用的外部服务。构建通过不能说明 DNS、Giscus OAuth、CDN 缓存或线上 API 已验证。

检查与验收

仓库 CI 的检查顺序见 ci.yml,具体脚本以 package.json 为准。

pnpm format
pnpm lint
pnpm test
pnpm check
pnpm build
pnpm test:built-pagination
pnpm test:built-restructure
pnpm test:built-markdown

三项 test:built-* 必须在本次成功构建后运行。它们分别验证分页与无 JS 回退、页面和菜单结构、Markdown/媒体/RSS 全文与本地资源。dev 预览不能代替生产构建。

改动 补充检查
只改仓库说明文档 格式、相对链接和锚点,以及与代码/配置的一致性;无需重跑无关页面交互
文章与友链 validate_content.py 基础预检,再构建并按需执行相关产物检查;预检不代替 Astro schema
列表、分类、标签、分页 对应 blog-browser/blog-tag-filter 单测与 built 分页、结构检查
图片、卡片、HTML/音视频 正文验证映射,检查源码资源与产物引用
RSS/canonical/sitemap 订阅验证映射,真实阅读器另验
布局、导航、主题、搜索、评论 对应真实浏览器脚本、深浅主题及 1440/390/320px 可读性与横向溢出;字体声明或 CSS 拆分改动另跑 scripts/verify-navigation-fonts.mjs,检查切页时已加载字体不回退
Last.fm 接口 属主和端点单测、固定载荷浏览器检查,部署后再验真实凭据与缓存
屏幕时间接口与区块 属主、端点、渲染单测,骨架/就绪与失败的真实浏览器检查,部署后再验 Blob 写入与缓存
旅行导入与页面 旅行验证;地图、选中与回放需要真实浏览器检查
python3 blog-content-publisher-skill/scripts/validate_content.py --root . --blog src/content/blogs/slug.md
python3 blog-content-publisher-skill/scripts/validate_content.py --root . --friends

浏览器脚本

scripts/verify-*.mjs 中面向 Ego 的脚本复用已有 TaskSpace,不自行管理服务。确认服务 cwd 属于当前 worktree,再将 __TASK_SPACE_ID__、__BASE_URL__ 替换为实际空间 ID 和服务日志的 Local 地址(含 base 与末尾 /),例如:

sed -e 's/__TASK_SPACE_ID__/<id>/g' \
  -e 's|__BASE_URL__|<实际 Local 地址>|g' \
  scripts/verify-nav-dropdown.mjs | ego-browser nodejs

按功能选用 verify-home-content.mjs、verify-toc-navigation.mjs、verify-theme-refresh.mjs、verify-accent-palette.mjs、verify-background-layering.mjs、verify-shell-alignment.mjs、verify-prose-overflow.mjs、verify-media-focus.mjs、verify-card-rails.mjs、verify-giscus.mjs、verify-listening.mjs 和 verify-listening-startup.mjs;以脚本内的占位符说明为准。目录检查覆盖 1200px 阈值。

verify-image-layouts.mjs 还需将 __REPO_ROOT__ 替换为当前 worktree 的绝对路径,它会创建并清理临时草稿和 SVG 夹具,不应修改真实文章。评论脚本不发送留言,OAuth 和评论持久化需单独用账号验收。

内容 skill 修改含实际图片排版、卡片或媒体的博客后,会启动或复用同 worktree 的 dev、核实目标文章 HTTP 成功再交付预览链接;纯文字或仅普通正文图不必预览。禁止启动或环境受限时明确说明未预览,不交付猜测的链接。

维护文档

README 是总览,docs/README.md 是查找入口,设计文档按功能维护现行契约,源码与测试是核实依据。新增规则放到已有主题,避免每次改动新建一份 SPEC。结构、交互和代码的有效变更记入 CHANGELOG.md 的未发布区;内容数据不记入,发布时再填写版本与日期。