ui-snapshot

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skill: ui-snapshot

Skill: ui-snapshot

Đúc kết từ phiên bonbon-ai 2026-09-19: 12 màn × desktop/mobile + 10 overlay của
fe/
(Next.js 14, Tailwind 3) gói trong 426 KB, Playwright 22 ảnh, 0 lỗi console.
沉淀自 bonbon-ai 2026-09-19 会话:将
fe/
的 12 个界面 × desktop/mobile 与 10 个 overlay(Next.js 14、Tailwind 3)打包在 426 KB 内;Playwright 生成 22 张截图,0 个 console 错误。

WHAT

WHAT(是什么)

Purpose và context

目的与背景

  • Purpose: một file
    .html
    duy nhất mở bằng double-click (không server, không mạng, không login) tái hiện đúng giao diện app thật — layout, token màu, font, icon, trạng thái (loading/empty/error/overdue…), overlay (modal, sheet, toast, tour) — với dữ liệu placeholder cứng.
  • Trigger (when to use):
    • Cần đưa giao diện cho người không chạy được app (sếp, designer, khách, reviewer, tài liệu wiki).
    • Cần bản mockup có dữ liệu mẫu để bàn UX/QC mà không đụng dữ liệu thật hay backend.
    • User nói 'snapshot UI', 'gói giao diện vào 1 file html', 'nén UIUX dự án', hoặc
      /ui-snapshot
      .
  • Non-goals: không thiết kế lại (→ hallmark/redesign), không chụp ảnh tĩnh app đang chạy (→ playwright-verify), không nhét dữ liệu thật, không giữ logic nghiệp vụ/API (nút hành động chỉ đổi state trong trang).
  • **目的:**生成唯一一个
    .html
    文件,可通过双击打开(无需 server、网络或登录),并用硬编码的 placeholder 数据准确复现真实应用界面——包括 layout、颜色 token、字体、图标、状态(loading/empty/error/overdue……)以及 overlay(modal、sheet、toast、tour)。
  • 触发条件(何时使用):
    • 需要把界面交付给无法运行应用的人(老板、设计师、客户、reviewer、wiki 文档)。
    • 需要带示例数据的 mockup,以便讨论 UX/QC,同时不接触真实数据或 backend。
    • 用户说“snapshot UI”“把整个界面打包成 1 个 HTML 文件”“压缩项目 UI/UX”,或调用
      /ui-snapshot
      。
  • **非目标:**不重新设计(→ hallmark/redesign),不对正在运行的应用进行静态截图(→ playwright-verify),不填入真实数据,也不保留业务逻辑/API(操作按钮仅在页面内切换 state)。

Mental model

思维模型

Vì sao PORT thay vì build/SSR app thật: app thật cần auth + backend + dữ liệu thật; snapshot bằng DOM thật sẽ kéo theo dữ liệu nhạy cảm và bundle lớn. Port sang vanilla JS với class chép nguyên văn + compile Tailwind bằng config thật cho ra đúng pixel mà không mang theo gì khác.
đọc HẾT JSX các trang → liệt kê màn + trạng thái + overlay → viết app.js (router hash, state, data cứng, 1 hàm/màn, nhánh desktop/mobile) → build.py (Tailwind config thật + font + icon subset + asset data URI) → shot.mjs verify → sửa → publish
.
之所以选择 PORT,而不是构建/SSR 真实应用,是因为真实应用需要 auth + backend + 真实数据;使用真实 DOM 制作 snapshot 会引入敏感数据和庞大的 bundle。移植为 vanilla JS,并逐字保留 class + 使用真实 config 编译 Tailwind,既能实现像素级一致,又不会夹带其他内容。
通读所有页面的 JSX → 列出界面 + 状态 + overlay → 编写 app.js(hash router、state、硬编码数据、每个界面一个函数、desktop/mobile 分支)→ 编写 build.py(真实 Tailwind config + 字体 + 图标子集 + 使用 data URI 的 asset)→ 用 shot.mjs 验证 → 修正 → 发布
。

Input và output contract

输入与输出约定

FieldRequired?Ý nghĩa
Inthư mục frontend (
--fe
) có
node_modules
cóđể dùng
tailwindcss
CLI + config của dự án
Indanh sách trang/routecó (tự dò
app/**/page.tsx
,
pages/
,
src/routes
)
phạm vi "toàn bộ UI"
Inngưỡng dung lượngkhông (5 MB)
--max-mb
Infont chính / logo / bannerkhông
--font
,
--asset NAME=path
Out
<repo>/…/DDMMYY-<project>-uiux-snapshot.html
cófile duy nhất, offline
Outbáo cáo: số màn, KB, ảnh verify, lệch so app thậtcótrung thực, liệt kê chỗ giả lập
字段是否必填含义
Infrontend 目录(
--fe
),其中包含
node_modules
是用于调用
tailwindcss
CLI 及项目自身的 config
In页面/route 列表是(自动探测
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、验证截图、与真实应用的差异是如实列出所有模拟项

Rules và capabilities

规则与能力

  • RULE-01 (MUST): Đọc HẾT file JSX của từng trang trước khi port (kể cả nhánh mobile, empty/loading/error, modal, sheet). Port từ trí nhớ = lệch UI.
  • RULE-02 (MUST): Class Tailwind chép NGUYÊN VĂN từ JSX, viết dạng chuỗi literal trong
    app.js
    (JIT chỉ thấy literal; ghép động
    bg-${x}
    sẽ mất class).
  • RULE-03 (MUST): Dữ liệu placeholder cứng, không bao giờ dữ liệu thật (không gọi API, không copy từ network capture/DB). Ngày dùng offset tương đối (
    D(-9)
    ) để trạng thái quá hạn ổn định theo thời gian.
  • RULE-04 (MUST): Tên icon viết dạng chuỗi có nháy (
    "search"
    ) để
    build.py
    subset font; icon động thì đặt tên đầy đủ trong map.
  • RULE-05 (MUST): Cùng breakpoint với app (vd 768px) và render nhánh desktop/mobile bằng JS (không dựa
    md:
    khi có chế độ ép mobile trong khung điện thoại).
  • RULE-06 (MUST): Asset ngoài (ảnh CDN, font Google) phải nhúng hoặc thay bằng nền/gradient — file phải chạy offline. Ghi rõ mọi chỗ thay thế trong báo cáo.
  • RULE-07 (MUST): Verify bằng
    shot.mjs
    cả desktop + mobile, đọc ảnh,
    NO ERRORS
    mới báo xong; vượt
    --max-mb
    = FAIL.
  • RULE-08 (SHOULD): Có panel demo (nút "UI") để nhảy tới mọi màn + bật trạng thái (loading/stale, lỗi, toast, tour, các state AI…), và chế độ Auto/Desktop/Mobile.
  • Capabilities: đọc codebase; Python 3 + Node + Tailwind CLI của dự án; mạng lúc build (Google Fonts, codepoints); Playwright để verify.
  • RULE-01 (MUST):移植前必须通读每个页面的所有 JSX 文件(包括 mobile 分支、empty/loading/error、modal、sheet)。凭记忆移植会导致 UI 偏差。
  • RULE-02 (MUST):逐字复制 JSX 中的 Tailwind class,在
    app.js
    中写成 literal 字符串(JIT 只能识别 literal;动态拼接
    bg-${x}
    会导致 class 丢失)。
  • RULE-03 (MUST):数据必须是硬编码的 placeholder,绝不能使用真实数据(不调用 API,不从 network capture/DB 复制)。日期使用相对 offset(
    D(-9)
    ),使 overdue 状态随时间保持稳定。
  • RULE-04 (MUST):图标名称写成带引号的字符串(
    "search"
    ),以便
    build.py
    对字体进行子集化;动态图标则必须在 map 中写全名。
  • RULE-05 (MUST):使用与 app 相同的 breakpoint(例如 768px),并通过 JS 渲染 desktop/mobile 分支(在手机框中强制 mobile 模式时,不能依赖
    md:
    )。
  • RULE-06 (MUST):外部 asset(CDN 图片、Google 字体)必须嵌入或替换为背景/gradient——文件必须能够离线运行。所有替换点都要写入报告。
  • RULE-07 (MUST):使用
    shot.mjs
    验证 desktop + mobile,并查看截图;只有在输出
    NO ERRORS
    后才能报告完成。超过
    --max-mb
    即为 FAIL。
  • RULE-08 (SHOULD):提供 demo panel(“UI”按钮),用于跳转到所有界面并切换状态(loading/stale、错误、toast、tour、各类 AI state……),同时支持 Auto/Desktop/Mobile 模式。
  • 能力:读取 codebase;使用 Python 3 + Node + 项目自带的 Tailwind CLI;构建时需要网络访问 Google Fonts 和 codepoints;使用 Playwright 进行验证。

Failure boundaries

失败边界

  • Dự án không dùng Tailwind →
    build.py
    để CSS trống: chép CSS module/styled vào template tay, hoặc clarify với user.
  • Không có mạng lúc build → font/icon không nhúng được → blocked (hoặc chấp nhận fallback system font, ghi rõ).
  • File vượt ngưỡng → giảm: bỏ weight font thừa, ảnh
    sips -Z
    nhỏ hơn, bớt dữ liệu mẫu; không cắt màn hình.
  • Framework khác (Vue/Svelte/Angular template) → vẫn áp dụng, chỉ đổi nguồn đọc class.
  • 项目不使用 Tailwind →
    build.py
    会生成空 CSS:手动将 CSS module/styled 复制到 template,或与用户确认。
  • 构建时无网络 → 无法嵌入 font/icon → blocked(或者接受 system font fallback,并清楚记录)。
  • 文件超出阈值 → 减少体积:移除多余的 font weight、使用
    sips -Z
    缩小图片、减少示例数据;不得删减界面。
  • 其他 framework(Vue/Svelte/Angular template)→ 仍然适用,只需更改读取 class 的来源。

HOW

HOW(如何执行)

Main workflow

主工作流

StepTypeInputsActionOutputs/exitFailure/next
W01deterministic
--fe
Dò route + layout + component dùng chung; đọc
tailwind.config
,
globals.css
,
design.md
nếu có
danh sách màn + tokenkhông Tailwind → FB1
W02judgmentJSX từng trangĐọc HẾT từng trang (RULE-01), ghi lại mọi trạng thái/overlay/nhánh mobileinventory màn × trạng thái—
W03effectinventoryTạo
<scratch>/app.js
từ
assets/app-skeleton.js
,
template.html
từ
assets/template.html
(thay
__TITLE__
,
__FONT__
); port từng màn, class nguyên văn, data cứng
app.js—
W04deterministicapp.js + template
python3 scripts/build.py --fe <fe> --src <scratch> --out <file> --font "<Font>" --asset LOGO=public/logo.png
file HTML + KBlỗi Tailwind → xem stderr; >max → FB3
W05deterministicfile
node scripts/shot.mjs <file> <scratch>/shots d-home=home m-home=home …
(cài
playwright
vào scratch nếu thiếu) rồi ĐỌC ảnh
ảnh +
NO ERRORS
lỗi → sửa app.js, lặp W04
W06effectfileĐặt vào repo (vd
llmwiki/html/DDMMYY-<project>-uiux-snapshot.html
), ghi log wiki nếu dự án có; báo cáo số màn, KB, chỗ giả lập
báo cáo—
步骤类型输入操作输出/退出条件失败/下一步
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 文件 + KBTailwind 错误 → 查看 stderr;超过 max → FB3
W05确定性file
node scripts/shot.mjs <file> <scratch>/shots d-home=home m-home=home …
(若缺少
playwright
,则安装到 scratch),然后查看截图
截图 +
NO ERRORS
出错 → 修正 app.js,重跑 W04
W06执行file放入 repo(例如
llmwiki/html/DDMMYY-<project>-uiux-snapshot.html
);如果项目支持,则写入 wiki 日志;报告界面数量、KB 和模拟项
报告—

Branches

分支

IDKindGuardHành viSkip / failureRejoin
B01conditionaltrang có dead-code UI (state không có đường vào)vẫn port nhưng chỉ mở qua panel demo, ghi chú "legacy"—W03
B02conditionalapp có devtool page tối/khác design systemport bằng inline style như bản gốc—W03
B03recoverychế độ mobile trên màn rộng lệch layoutkhung
#frame
có
transform
để
fixed
bám khung;
#app
là vùng cuộn; override
.h-screen/.min-h-screen
= 100% (đã có trong template)
—W05
ID类型条件行为跳过/失败汇合点
B01条件分支页面包含无法进入的 dead-code UI(state 没有可到达路径)仍然移植,但只能通过 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%(template 中已有)
—W05

Validation và stopping

验证与停止条件

Tất định:
build.py
exit 0 và dưới ngưỡng;
shot.mjs
in
NO ERRORS
cho mọi màn desktop + mobile. Cần mắt: so ảnh với app thật/Figma (màu, khoảng cách, chữ tiếng Việt có dấu). Dừng khi mọi màn trong inventory có ảnh sạch và báo cáo đã liệt kê chỗ giả lập.
确定性检查:
build.py
exit 0 且文件低于阈值;
shot.mjs
对每个界面的 desktop + mobile 输出
NO ERRORS
。人工检查:将截图与真实应用/Figma 对比(颜色、间距、带声调符号的越南语文本)。当清单中的每个界面都有无错误截图,且报告已列出所有模拟项时停止。

Examples

示例

  • Positive: bonbon-ai
    fe/
    → login, dashboard overview/pending/overdue, filter theo phòng ban/loại HĐ, chi tiết phiếu 3 tab, VS Code overlay, AI tracker, sheet/modal/toast/tour → 426 KB, 79 icon, 22 ảnh verify, 0 lỗi.
  • Boundary: dự án ảnh nền hero 3 MB từ CDN → thay gradient + ghi "khác app thật: ảnh nền login" thay vì nhúng làm file vượt ngưỡng.
  • 正向: bonbon-ai
    fe/
    → 登录、dashboard 概览/pending/overdue、按部门/合同类型筛选、带 3 个标签页的单据详情、VS Code overlay、AI tracker、sheet/modal/toast/tour → 426 KB、79 个图标、22 张验证截图、0 个错误。
  • 边界: 项目的 hero 背景图从 CDN 加载且大小为 3 MB → 替换为 gradient,并记录“与真实应用不同:登录背景”,而不是嵌入后导致文件超出阈值。

Test tất định

确定性测试

python3 scripts/build.py --fe <fe> --src assets-copy --out /tmp/t.html
với
assets/app-skeleton.js
(đổi tên app.js) +
assets/template.html
phải ra file < 1 MB, rồi
node scripts/shot.mjs /tmp/t.html /tmp/shots d-home=home m-home=home
in
NO ERRORS
.
使用
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
。