关于 ui-snapshot
将前端应用界面移植为单个离线 HTML 文件的技能,供设计评审、文档和无法运行应用的相关人员查看。它覆盖页面状态和弹层,并通过桌面与移动视图截图验证结果。
主要功能
- 01读取页面、状态与弹层
- 02复用原有 Tailwind 类名
- 03用占位数据构建界面
- 04生成单文件离线 HTML
- 05验证桌面与移动视图
- 06报告模拟内容和文件大小
适用场景
- 01向无法运行应用的评审者展示界面
- 02用样例数据开展 UX 或 QC 讨论
- 03为项目文档提供离线界面演示
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill ui-snapshot安装后在 Claude Code 中输入/ui-snapshot确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/app-skeleton.jstemplate.htmlscripts/build.pyshot.mjs详细介绍
技能:ui-snapshot
总结自 bonbon-ai 2026-09-19 的一轮工作:fe/ 中 12 个页面 × 桌面端/移动端 + 10 个 overlay(Next.js 14、Tailwind 3),打包后为 426 KB;使用 Playwright 生成 22 张截图,控制台错误数为 0。
WHAT
用途与背景
- **用途:**生成一个可双击打开的单独
.html文件(无需服务器、网络或登录),准确复现真实应用界面——布局、颜色 token、字体、图标、状态(加载中/空/错误/逾期……)、overlay(模态框、sheet、toast、引导)——并使用固定的占位数据。 - 触发场景(何时使用):
- 需要向无法运行应用的人展示界面(老板、设计师、客户、审核者、wiki 文档)。
- 需要带示例数据的 mockup 来讨论 UX/QC,且不触及真实数据或后端。
- 用户说“UI 快照”“把界面打包到一个 html 文件”“压缩项目 UIUX”或使用
/ui-snapshot。
- **非目标:**不重新设计(→ hallmark/redesign),不截取正在运行的应用(→ playwright-verify),不放入真实数据,不保留业务逻辑/API(操作按钮只改变页面内的状态)。
心智模型
为什么要 PORT,而不是构建/SSR 真实应用:真实应用需要身份验证 + 后端 + 真实数据;使用真实 DOM 制作快照会带入敏感数据和大型 bundle。移植到原生 JS,并原样复制 class + 使用真实配置编译 Tailwind,即可精准还原像素,同时不带入其他内容。
完整阅读各页面的 JSX → 列出页面 + 状态 + overlay → 编写 app.js(hash 路由、状态、固定数据、每个页面一个函数、桌面端/移动端分支)→ build.py(真实 Tailwind 配置 + 字体 + 图标子集 + asset data URI)→ shot.mjs 验证 → 修复 → 发布。
输入和输出约定
| Field | Required? | 含义 | |
|---|---|---|---|
| In | 前端目录(--fe),包含 node_modules | 是 | 用于调用 tailwindcss CLI 和项目配置 |
| In | 页面/路由列表 | 是(自动检测 app/**/page.tsx、pages/、src/routes) | “全部 UI”的范围 |
| In | 文件大小上限 | 否(5 MB) | --max-mb |
| In | 主字体 / logo / banner | 否 | --font、--asset NAME=path |
| Out | <repo>/…/DDMMYY-<project>-uiux-snapshot.html | 是 | 唯一文件,离线可用 |
| Out | 报告:页面数、KB、验证截图、与真实应用的差异 | 是 | 如实列出模拟部分 |
规则与能力
- RULE-01(MUST):移植前完整阅读每个页面的 JSX 文件(包括移动端分支、空/加载中/错误状态、模态框、sheet)。凭记忆移植 = UI 不准确。
- RULE-02(MUST):从 JSX 原样复制 Tailwind class,在
app.js中写成字符串字面量(JIT 只能识别字面量;动态拼接bg-${x}会导致 class 丢失)。 - RULE-03(MUST):只使用固定的占位数据,绝不使用真实数据(不调用 API,不从网络捕获数据/DB 复制数据)。日期使用相对偏移(
D(-9)),确保逾期状态不会随时间变化。 - RULE-04(MUST):图标名称必须写成带引号的字符串(
"search"),以便build.py生成字体子集;动态图标应在 map 中列出完整名称。 - RULE-05(MUST):使用与应用相同的断点(例如 768px),并通过 JS 渲染桌面端/移动端分支(当手机框架中启用强制移动模式时,不要依赖
md:)。 - RULE-06(MUST):外部资源(CDN 图片、Google Fonts 字体)必须嵌入或替换为背景/渐变——文件必须离线运行。在报告中明确说明所有替换之处。
- RULE-07(MUST):使用
shot.mjs验证桌面端 + 移动端,检查截图,只有NO ERRORS才能报告完成;超过--max-mb= FAIL。 - RULE-08(SHOULD):提供 demo 面板(“UI”按钮),以跳转到所有页面并启用状态(加载中/stale、错误、toast、引导、各种 AI 状态),以及 Auto/Desktop/Mobile 模式。
- 能力:阅读代码库;Python 3 + Node + 项目的 Tailwind CLI;构建时联网(Google Fonts、codepoints);使用 Playwright 验证。
失败边界
- 项目未使用 Tailwind →
build.py会生成空 CSS:将 CSS module/styled 手动复制到模板中,或向用户确认。 - 构建时无法联网 → 无法嵌入字体/图标 → 受阻(或接受回退到系统字体,并明确说明)。
- 文件超过阈值 → 缩减:移除多余的字体 weight,使用更小的图片
sips -Z,减少示例数据;不要删减屏幕。 - 使用其他框架(Vue/Svelte/Angular template)→ 仍可应用,只需更换读取 class 的来源。
操作方式
主要工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/后续 |
|---|---|---|---|---|---|
| W01 | 确定性 | --fe | 检查 route、layout 和共用 component;如存在,则读取 tailwind.config、globals.css、design.md | 屏幕列表 + token | 未使用 Tailwind → FB1 |
| W02 | 判断 | 每个页面的 JSX | 读取每个页面的全部内容(RULE-01),记录所有状态/overlay/mobile 分支 | 屏幕 × 状态清单 | — |
| W03 | 效果 | 清单 | 从 assets/app-skeleton.js 创建 <scratch>/app.js,从 assets/template.html 创建 template.html(替换 __TITLE__、__FONT__);逐个移植屏幕,class 保持原文,数据写死 | app.js | — |
| W04 | 确定性 | app.js + template | python3 scripts/build.py --fe <fe> --src <scratch> --out <file> --font "<Font>" --asset LOGO=public/logo.png | HTML 文件 + KB | Tailwind 出错 → 查看 stderr;超过最大值 → FB3 |
| W05 | 确定性 | 文件 | node scripts/shot.mjs <file> <scratch>/shots d-home=home m-home=home …(如果 scratch 中缺少 playwright,则安装)然后读取图片 | 图片 + NO ERRORS | 出错 → 修改 app.js,重复 W04 |
| W06 | 效果 | 文件 | 放入 repo(例如 llmwiki/html/DDMMYY-<project>-uiux-snapshot.html),如果项目有 wiki,则记录日志;报告屏幕数量、KB,以及模拟内容的位置 | 报告 | — |
分支
| ID | 类型 | 条件 | 行为 | 跳过/失败 | 汇合 |
|---|---|---|---|---|---|
| B01 | 条件 | 页面包含 dead-code UI(状态没有可达路径) | 仍然移植,但仅通过 demo panel 打开,并注明 "legacy" | — | W03 |
| B02 | 条件 | app 有深色/不同于 design system 的 devtool page | 使用 inline style 按原样移植 | — | W03 |
| B03 | 恢复 | 宽屏上的 mobile 模式布局错位 | #frame 框架使用 transform,让 fixed 元素依附于框架;#app 是滚动区域;将 .h-screen/.min-h-screen 覆盖为 100%(模板中已有) | — | W05 |
验证与停止
确定性检查:build.py 退出码为 0 且文件低于阈值;shot.mjs 为所有 desktop + mobile 屏幕打印 NO ERRORS。人工检查:将图片与实际 app/Figma 对比(颜色、间距、带变音符号的越南语文字)。当清单中的每个屏幕都有清晰图片,且报告已列出模拟内容的位置时,即可停止。
示例
- 正面示例: bonbon-ai
fe/→ login、dashboard overview/pending/overdue、按部门/合同类型筛选、包含 3 个 tab 的票据详情、VS Code overlay、AI tracker、sheet/modal/toast/tour → 426 KB、79 个图标、验证 22 张图片、0 个错误。 - 边界情况: 项目通过 CDN 加载的 hero 背景图为 3 MB → 改用渐变,并注明“与实际 app 不同:登录背景图”,而不是嵌入图片导致文件超过阈值。
确定性测试
使用 assets/app-skeleton.js(重命名为 app.js)和 assets/template.html 执行 python3 scripts/build.py --fe <fe> --src assets-copy --out /tmp/t.html,应生成小于 1 MB 的文件;随后执行 node scripts/shot.mjs /tmp/t.html /tmp/shots d-home=home m-home=home,应打印 NO ERRORS。