调研收官产物入库:主报告(架构 C''=Astro SSG+gitea 双写作流、 Artalk 评论、分片 webfont、双语预译管线、多端适配规格、 Phase 0-5 实施规划)+ 五份侦察原稿 + 可交互单文件样板 (三路线×明暗×五页型,命令面板/终端/热力图/masonry)。 Co-authored-by: GLM-5.3
18 KiB
task-2 · 极客交互设计侦察报告(极客精神设计语言:真实案例 × 可落地实现)
侦察员 @agent-aeff1b · 2026-10-24 方法:所有案例均于本次用 curl 实际抓取验证(HTTP 状态 / 页面源码标记 / 开源仓源码 / npm registry / caniuse 官方数据),命令面板与终端站深挖到 JS bundle 与命令表。抓不到、不命中的一律如实标注为负发现。技术基线:Astro SSG + 自托管 Gitea,视觉路线「灰阶骨架×分轨正文」。
1. 命令面板 Ctrl+K
实测案例
| 站点 | 抓取证据 | 说明 |
|---|---|---|
| Starlight / Astro 官方文档 starlight.astro.build | HTTP 200;页面源码含 aria-keyshortcuts="Control+K" ×1 + pagefind ×3 |
静态站 + Pagefind + 自定义模态的官方参考实现,MIT 源码:withastro/starlight → packages/starlight/src/components/Search.astro(已实抓源码头 25 行:按钮 aria-keyshortcuts="Control+K" + pagefind 翻译注入 + data-open-modal) |
| spectre.lou.gg(louisescher/spectre,164★) | HTTP 200;服务端 HTML 直接含 <input id="search" placeholder="Search (Ctrl+K)">,且 HTML 内有 pagefind-ignore= 属性、pagefindInitialized = false(首次聚焦才懒加载 Pagefind) |
Astro 原生终端风主题,与本博客技术栈同源,Ctrl+K 搜索框静态可抓,是「静态站 Ctrl+K + Pagefind」最佳抄写对象 |
| paco.me(Paco Coursey,cmdk 作者本人站) | HTTP 200;源码含 ⌘K、command menu、cmdk 字样 |
cmdk 生态的活样本 |
| blog.maximeheckel.com(Maxime Heckel 博客) | 开源仓 MaximeHeckel/blog.maximeheckel.com package.json 实抓:依赖 cmdk ^1.1.1 |
个人博客用 cmdk 的实证 |
未验证(如实说明):leerob.com / rauchg.com / kentcdodds.com / brianlovin.com / joshwcomeau.com 首页静态 HTML 均无面板标记(客户端懒渲染),未继续深挖各自 bundle,不作案例引用。kentcdodds/kentcdodds.com 与 sreetamdas/sreetamdas.com 的 package.json 中均无 kbar/cmdk。
库与取舍(npm registry 实抓数据)
- cmdk:React 无样式 primitive(UI 全自理),周下载 26,647,174。适合已有 React 岛的站。
- kbar:即插即用 React 面板(自带动画/快捷键注册/持久化),周下载 226,077;README 实抓:「plug-n-play React component…built in animations and fully customizable components」。
- 静态站推荐:自写 vanilla TS(~150–200 行,零运行时框架)。Pagefind 官方 JS API 文档实抓(pagefind.app/docs/api/,HTTP 200):
pagefind.search()×8、pagefind.debouncedSearch()×3、pagefind.options()×3、pagefind.filters()×1 —— 程序化搜索接口完备,就是为自定义 UI 准备的。
Pagefind 聚合进面板的实现路径
astro build后跑pagefind --site dist出索引(或用astro-pagefind集成,567★,README 实抓:构建时自动建索引 + 官方声明支持 Astro View Transitions)。- 自写模态:全局
keydown监听 Ctrl/Cmd+K 与/→ 打开<div role="dialog">(或<dialog>)。 - 面板数据三层:动作项(静态数组:切主题、跳 gitea、复制 RSS)+ 页面/文章(Pagefind
search(query)返回 pages + 文内摘要)+ 分组渲染。 - spectre 的懒加载模式值得抄:
pagefindInitialized=false,首次打开面板才import('/pagefind/pagefind.js'),不拖首屏。
对本博客的适配建议
Astro 零框架站不要为面板引 React(cmdk/kbar 都会把 React runtime 拖进来)。抄 Starlight Search.astro 的结构 + spectre 的懒加载,自写 ~200 行 vanilla 模态。灰阶骨架下,面板天然「一整层黑底等宽字浮层」,视觉零违和。
2. 键盘快捷键惯例
实测案例(GitHub 官方文档页逐字取证)
docs.github.com/en/get-started/accessibility/keyboard-shortcuts(HTTP 200)HTML 表格实抓:
<kbd>S</kbd> or <kbd>/</kbd>→ "Focus the search bar"(/ 聚焦搜索实锤)<kbd>G</kbd> <kbd>N</kbd>→ notifications;<kbd>G</kbd> <kbd>C</kbd>→ Code tab;G P→ PRs;G A→ Actions;G W→ Wiki(g-chords 和弦导航实锤)<kbd>?</kbd>→ "brings up a dialog box that lists the keyboard shortcuts available"(? 帮助浮层实锤)<kbd>Esc</kbd>→ 关闭悬浮卡
未验证(如实说明):Gmail(support.google.com/mail/answer/6594)与 Linear(linear.app/keyboard-shortcuts 与 /docs/shortcuts 404)键位页均为客户端渲染,静态抓取零命中,不能引用为抓取实证;GitHub 证据已足够作键位锚点。 负发现:「t 切主题」「g h 回首页」未找到可验证的个人博客公开实例——这反而是原创空间:惯例来自 GitHub/Gmail,移植到博客即成特色。
实现路径
- 自写(推荐,~120–150 行):一个
keydown监听 + 200ms 和弦缓冲(识别g h)+ 输入框聚焦时旁路 +?帮助浮层。无依赖。 - 或配 tinykeys(jamiebuilds,周下载 193,770,约 400B)管绑定,自写部分只剩 chord 逻辑与浮层。
- 主题切换若想配 View Transitions 圆形扩散动画:ocavue/astro-theme-toggle(62★,"ripple-style theme toggle animation to your Astro project",GitHub API 实抓)。
对本博客的适配建议
P0 键位集:/ 聚焦搜索、? 帮助浮层(可发现性的关键,务必做)、t 切主题、g h 回首页、Esc 关一切浮层。键位表数据与 ? 浮层同源生成,永不失同步。灰阶骨架 + 等宽字提示角标(如导航项旁的 g h 小字)本身就是极客视觉语言的一部分。
3. 构建透明化(页脚 commit hash · 构建时间)
实测案例
| 站点 | 抓取证据 |
|---|---|
| sreetamdas.com(sreetamdas/sreetamdas.com,Next.js,MIT) | 仓内 scripts/generate-build-info.mjs 全文实抓:WORKERS_CI_COMMIT_SHA / CF_PAGES_COMMIT_SHA / GITHUB_SHA / git rev-parse HEAD 四重回退 → 写 src/build-info.json,字段 {branch, commit(前7位), commitUrl, time: ISO时间}。注:其站静态 HTML 页脚未见 hash(该信息主要供 CI 冒烟/接口用),展示环节未验证 |
| mldangelo.com(mldangelo/personal-site,1695★ 个人站模板,Next 静态导出) | sourcegraph 实抓源码:src/components/Stats/Site.tsx 含 built_commit: builtCommit();配套测试断言页面上存在 'Built from commit' 行 —— 个人站模板直接内置「构建透明化」区块,live 站 HTTP 200 |
负发现:gwern.net、survivejs.com、search.nixos.org、notes.eatonphil.com、drewdevault.com、mxb.dev、darekkay.com、fasterthanli.me、joshfinnie.com、stefanjudis.com 十个极客向站首页/页脚抓取均无 commit hash —— 说明这在主流个人站里罕见,做了反而差异化。
Astro 实现路径
- 零依赖自写(推荐,~20 行):
astro.config.mjs里页脚组件读vite: { define: { 'import.meta.env.GIT_COMMIT_SHA': JSON.stringify(execSync('git rev-parse HEAD').toString().trim()), 'import.meta.env.GIT_COMMIT_DATE': JSON.stringify(execSync('git log -1 --format=%cI').toString().trim()), }}import.meta.env.GIT_COMMIT_SHA.slice(0,7)。sreetamdas 的四重回退模式(CI 环境变量优先)值得照抄。 - 现成包(npm registry 实证存在,但体积/维护一般):
vite-plugin-git-revision-info@1.1.0、git-revision-vite-plugin、@jinixx/vite-plugin-git-revision。 - CI 注意:Gitea Actions 的 checkout 步骤默认浅克隆也能拿到 HEAD sha(或直接用
gitea.event.head_commit.id注入环境变量)。
对本博客的适配建议
页脚一行灰字:built from a1b2c3d · 2026-10-24 18:51 UTC,hash 链接到自托管 gitea 的 commit 页。半小时代价,极客气质浓度极高。
4. 贡献活动图(自托管 Gitea 数据从哪来)
核心实测结论:Gitea/Forgejo 原生就有热力图 API
gitea.com/swagger.v1.json实抓:存在唯一热力图路由GET /api/v1/users/{username}/heatmap,schemaUserHeatmapData = {contributions, timestamp}。- 真实数据双验证:
gitea.com/api/v1/users/lunny/heatmap与codeberg.org/api/v1/users/6543/heatmap均 HTTP 200,返回[{"timestamp":1760616000,"contributions":6},…](事件级 Unix 秒粒度,前端自行聚合到日/周格子)。 - CORS 实测:gitea.com 与 codeberg.org 对 API 请求均返回
access-control-allow-origin: *→ 静态站构建时拉没问题,甚至浏览器运行时直拉也通。
GitHub 工具能否指过来?
不能直接换标。github-readme-stats / contribution-graph 类方案依赖 GitHub GraphQL 的 contributionsCollection(REST 根本没有贡献端点),无法指向 Gitea。生态佐证(GitHub 搜索实抓):oliver-drewing/forgeheat(Forgejo 热力图挂件)、BenevolentFutures/forgejo-github-sync(反向把自托管提交同步养 GitHub 图)——「自托管后贡献图怎么办」是真实普遍痛点,各自造轮子。
自建数据源方案(git log 统计 → JSON)
git -C /path/repo log --all --pretty=format:'%ad' --date=unix \
| awk -v d=$(date +%s) '{day=strftime("%Y-%m-%d",$1); c[day]++} END {for(k in c) print k, c[k]}' > contrib.json
- 多仓循环合并即可;优点:算本地全历史(含从 GitHub 迁移来的仓、heatmap 端点统计不到的活动)、无网络依赖、CI 里必成。
- 也可和 heatmap API 并用:API 为主、git log 兜底。
对本博客的适配建议
构建时 fetch https://<自家gitea>/api/v1/users/<user>/heatmap → 聚合成 53×7 格 SVG/CSS grid,灰阶色阶恰好是热力图的完美配色(从 #ececec 到 #111 的七档)。失败时回退 git log 本地统计。~120 行 + 一个聚合函数。
5. 终端彩蛋页
实测案例(GitHub search "terminal portfolio" + 首页/JS bundle 抓取)
| 站点 | 抓取证据 |
|---|---|
| terminal.satnaing.dev(satnaing/terminal-portfolio,824★,React+TS) | bundle(277KB)实抓,命令表坐实:help ×3、whoami、pwd、history、echo、about、projects、clear、welcome —— 真·可交互终端站 |
| codenerve.github.io(CodeNerve,188★,纯 vanilla) | index.js 全文仅 2,999 字节:keydown 监听 + ls ×10 等命令 —— 自写 switch 方案极轻的活实证 |
| term.fathi.me(m4tt72/terminal,1564★,"Terminal style website") | SPA 壳站,31KB bundle 未能静态取证命令表(如实注明);star 数佐证品类成熟度 |
| spectre.lou.gg(louisescher/spectre,164★) | Astro 原生终端风主题(见 §1,还带 Ctrl+K),与技术栈同源,可整主题借鉴或只借 its CSS |
实现路径
- 自写 switch(推荐,~150–300 行,零依赖):隐藏 input 捕获 + 命令注册表(
{help, whoami, ls, cat, clear, exit…})+ 上下历史。codenerve 的 3KB 证明下限极低。 - 库:jQuery Terminal(jcubic,老牌全功能,自带多级命令/表单支持,风格偏 jQuery 时代)、react-terminal(需 React)、xterm.js(真终端模拟器,VS Code 同款——能跑、但过重,用于彩蛋页杀鸡用牛刀)。
对本博客的适配建议
/terminal 路由作彩蛋:不进主导航,藏在 ? 帮助浮层提示一句 hint: try /terminal(极客自己会发现的秘密)。命令组:help / whoami(输出个人签名档)/ ls blog / cat about.txt / gpg --recv-key <指纹>(真指纹,链接到 key 文件)/ exit(动画后跳回首页)。CRT 扫描线 + 琥珀色单色可选(灰阶骨架里允许一处 CRT 绿或琥珀做点睛)。
6. 页面转场(Astro View Transitions)
实测案例
| 站点 | 抓取证据 |
|---|---|
| mazipan.space(mazipan/mazipan.space,102★ 个人站+博客) | 线上 HTML 实抓(HTTP 200):含 ClientRouter ×1 + view-transition 标记 ×3 —— 个人博客真实用例 |
| astro-theme-reimu(D-Sketon,79★,demo: d-sketon.github.io/astro-theme-reimu) | sourcegraph 全网代码检索命中该仓 .astro 文件含 ClientRouter —— 中文圈在用的博客主题实证 |
| 官方文档 docs.astro.build/en/guides/view-transitions/ | 实抓:ClientRouter ×45、prefers-reduced-motion 独立章节 ×12、transition:animate ×13、不支持的浏览器的 fallback 行为章节 |
浏览器兼容(caniuse 官方数据实抓,view-transitions.json)
- Chrome 111+ ✅、Safari 18.0+ ✅、Firefox 144+ ✅(143 仍在 flag 后)。
- 2026 年现状:三大引擎全绿。Astro 的
ClientRouter用的是同文档转场(MPA 导航模拟),落在上述支持范围内;更老浏览器走fallback(默认 animate 模拟 / 可设 none 直切)+ reduced-motion 降级,无破坏性。
对本博客的适配建议
<ClientRouter /> 一行接入 + 一段保险 CSS:
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
转场动画克制:正文区轻微 fade/slide(呼应「分轨」——轨道间的内容流动),骨架(顶栏/页脚)用 transition:persist 常驻不闪。主题切换想加圆形扩散可参考 ocavue/astro-theme-toggle 的 ripple 方案与 VT 打配。
7. 开源项目墙(自托管 Gitea 动态拉卡片)
数据面实测(codeberg.org / gitea.com 同源 API)
GET /api/v1/repos/search?limit=2 实抓返回字段(Forgejo/Gitea 通用):
{ "full_name": "...", "description": "...", "website": "...", "language": "C",
"stars_count": 1, "forks_count": 0, "html_url": "...", "avatar_url": "", "updated_at": "..." }
主语言、star、描述、网站全有,卡片所需字段一次到位。GET /api/v1/users/{user}/repos 同理。CORS *(§4 实测)→ 构建时拉、运行时拉皆可。
消费者案例(诚实负发现 = 差异化机会)
- sourcegraph 全网代码检索
api/v1/repos/search:消费者仅 linuxserver/Heimdall-Apps(应用目录元数据脚本),无个人博客。 gitea lang:astro全网:仅 RayLabsHQ/gitea-mirror(镜像工具,API 用法可参考)。- 结论:个人博客从自托管 git 动态拉项目墙,没有现成公开案例 —— 没得抄,但也意味着做出来就是独一无二的开源自证。
- 语言颜色:Gitea API 不带色值;用 github-linguist/linguist 的
languages.yml作映射(实抓样本:Go#00ADD8、TypeScript#3178c6)。
Astro SSG 实现路径(~80 行)
---
// src/pages/projects.astro(frontmatter 在构建时执行)
const GITEA = 'https://git.example.com';
const repos = await fetch(`${GITEA}/api/v1/users/me/repos?limit=30`)
.then(r => r.json()).catch(() => JSON.parse(cachedFallback)); // 失败读上次缓存 JSON
---
构建时执行 = 零 CORS 问题、零客户端 JS;Gitea Actions 上 push 触发重建保证新鲜度;pinned 置顶仓用手动数组覆盖排序。
对本博客的适配建议
/projects 分轨页:卡片 = 语言色点(灰阶骨架里唯一允许的品牌色点缀,恰与「开源」语义互文)+ star 数 + 一行描述 + updated_at。页脚 built from <hash>(§3)→ 点击即达同源 gitea commit——构建透明化与项目墙共享同一自托管源,叙事闭环。
极客设计语言清单(性价比分级)
| 级别 | 项 | 实现方式 | 工作量 | 实证锚点 |
|---|---|---|---|---|
| P0 | 键盘基础集:/ 搜索、? 帮助浮层、t 主题、g h 回首页 |
自写 vanilla(keydown+chord buffer+浮层) | ~120–150 行,半天 | GitHub 键位表逐字实抓 |
| P0 | 页脚构建信息(hash+时间+commit 链接) | vite.define 注入或抄 sreetamdas 脚本 | ~20 行,半小时 | sreetamdas/mldangelo 源码实抓 |
| P0 | View Transitions + reduced-motion 降级 | <ClientRouter /> + 5 行 CSS |
半小时 | mazipan.space 实抓;三引擎全绿 |
| P0 | 开源项目墙 | 构建时 fetch gitea API 渲染卡片 | ~80 行,半天 | API 字段/CORS 实测 |
| P1 | Ctrl+K 命令面板(搜索+动作聚合) | 自写 vanilla 模态 + Pagefind JS API(懒加载) | ~200 行,一天 | Starlight Search.astro / spectre 实抓 |
| P1 | Gitea 贡献热力图 | heatmap API(或 git log 兜底)→ 灰阶 SVG 格 | ~120 行,一天 | heatmap 端点双站 200 实测 |
| P2 | /terminal 终端彩蛋页 |
自写命令 switch | ~200–300 行,一天 | codenerve 3KB 实证;satnaing 824★ |
| P2 | 全 g-chords 体系(g p 项目 / g b 博客) | 扩展 §2 chord 表 | +30 行 | GitHub G+N/C/P 模式移植 |
协同叙事:所有键位汇聚在 ? 浮层(可发现性)→ 面板是极客动线中枢(搜索+动作+彩蛋入口)→ 页脚 hash 与项目墙共享自托管 gitea 源(开源自证闭环)→ 热力图是这套语言里唯一的「数据可视化」,用灰阶色阶呈现正好。「艺术文学的美观」由灰阶骨架承担,「极客精神」由这层可交互的等宽字神经系统承担——两者不抢戏。
未验证/存疑清单(全部如实声明)
- leerob.com / rauchg.com / kentcdodds.com / brianlovin.com / joshwcomeau.com 的面板:静态 HTML 无标记(客户端渲染),未逐一深挖 bundle。
- Gmail / Linear 键位官方页:JS 渲染无法静态取证(GitHub 证据已足为键位锚点)。
- term.fathi.me 的命令表:bundle 未能静态取证。
- 「t 切主题」「g h 导航」在个人博客上:未找到可验证公开实例(属 GitHub/Gmail 惯例移植,无先例包袱)。
- 「个人博客动态拉自托管 git 项目墙」:全网无现成公开案例(负发现,同时是机会点)。
- sreetamdas.com 的 build-info:生成脚本实抓确凿,但页脚展示环节未在静态 HTML 验证到。