# Build Product Demo

> 为 landing page 或产品介绍制作、修改忠于真实应用的模拟演示，包括自动播放动画和使用真实前端的交互沙盒。适用于还原产品 UI、编排鼠标与输入动作、模拟消息及工具调用、修复动画穿帮；普通营销排版或真实后端功能开发不属于本技能的主要范围。

- Skill: `felinics/build-product-demo` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add felinics/build-product-demo`
- Raw SKILL.md: https://api.skillmd.com/api/skills/felinics/build-product-demo/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: felinics (https://skillmd.com/u/felinics)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/felinics/build-product-demo

---


# 制作可信的产品模拟演示

演示可以模拟数据和执行环境，但界面必须让产品用户认得出来，动作必须有因果关系。视觉像、操作通、状态一致，是三个独立的验收目标。

## 先辨认演示形态

检查当前页面实际挂载了什么，再选择改动位置。一个仓库可能同时有视频、手绘场景组件和嵌入式真实应用，不能因为某个文件名包含 Demo 就认定它是当前入口。

- **自动播放的功能片段**：适合聚焦少量动作。优先复用已有组件或按源码裁剪，不必为一个小场景启动整个产品。
- **可交互的产品沙盒**：用户能切换会话、打开文件、展开工具调用时，优先评估复用真实前端，在数据与传输边界模拟。重画整个应用很容易丢失产品细节和状态关联。
- 不因复用前端而擅自扩大为真实后端、部署或修改生产应用；也不因为最初是动画，就强迫后续交互需求继续使用假控件。

本仓库工作先读 [Memoh 实现索引](references/memoh-implementation.md)，其中区分了四宫格动画与真实前端沙盒。

## 从运行界面追到渲染源码

在画 UI 前完成一条最短证据链：

1. 确认用户指定的页面、端口、checkout 和分支。端口对应另一个工作树时，应读实际运行的那份源码。记录现有未提交改动，保护其他工作的文件。
2. 实际观察相关状态：初始页面、展开菜单、操作进行中、完成结果。读取源码不能替代看屏幕，截图也不能证明状态如何转换。用现有登录态做只读查看；观察安装流程可以打开并取消弹窗，无需真的安装。
3. 追到负责渲染的组件、样式 token 和状态模型。至少弄清顶栏、侧栏、输入框、消息、弹窗的所属层级。桌面原生控件可能由 Electron 或操作系统提供，不在网页组件里。
4. 区分可裁剪的信息和不可改写的产品语义。窗口顶栏不是通用浏览器标签；Agent 菜单不一定是模型菜单；包安装不等于 Connector 授权；连续工具调用不一定逐条显示。

参考站点用于研究布局、缩放、节奏和留白，产品内部结构由自己的真实产品决定。不要顺手加入发光背景、虚构状态徽章、口号、过大的标题或与产品无关的作品集来填空。

用户要求研究参考站源码时，可从页面实际加载的 CSS/JS 定位实现，下载公开发布资源并格式化阅读。核实响应确实是代码，不能把 403/验证页当作源码。区分原始源码、编译后的发布 JS、DOM 和计算样式；没有取得原始 TSX 时如实说明。保留可复查来源，不把临时下载目录作为 skill 的运行依赖。

## 让 UI 和数据来自同一个模型

对于真实前端沙盒，优先保持渲染器、状态更新和交互路径原样，在 transport/fixture 层注入模拟结果。保留 vendor 来源版本、许可证和必要的局部补丁说明。用 iframe 隔离样式时，还要单独检查存储、网络和路由边界；iframe 本身不保证隔离宿主凭证。

模拟数据必须连贯：目录与文件读取一致，列表与详情共享实体，发送消息与历史回读一致，工具调用输入、输出、状态及时间顺序互相对应。不要用“所有未知请求都返回空成功”掩盖缺失行为。对于明确无后端的演示，未知 API 和未支持的外部请求应在本地明确失败，而非回落到真实服务。

对于自动动画，使用小而明确的场景状态。消息正文、过程块和工具详情按真实组件职责组织。以 Memoh 为例，连续 tool/reasoning 会聚合为过程块，单条调用、当前步骤、完成态摘要有不同渲染方式；不能用几行带箭头的文字代替全部逻辑。

未上线或不存在的示例数据可以服务已授权的演示，但要与真实模型兼容，并在交付说明中区分示例与现有产品能力。

## 缩放整幅应用，而不是分别缩字号

将应用内容放在固定逻辑尺寸的画布里，用容器尺寸计算统一缩放，字体、图标、边距、弹窗和鼠标共用同一坐标系。常用形式：

```text
scale = min(最大展示比例, 可用宽度 / 逻辑宽度, 可用高度 / 逻辑高度)
展示占位 = 逻辑尺寸 × scale
```

宽度驱动的展示可省略高度约束，但要保证占位和裁切是有意设计的。使用 ResizeObserver 更新尺寸；变换原点通常取左上角。

外层卡片按屏幕响应式排列，内部桌面应用按比例缩放，不因手机视口而自动套用产品移动版布局。缩放和裁剪的程度由信息可读性决定；本次用过的画布尺寸、60%/70% 比例、浅色卡片或圆角都不是通用规范。保留足够操作空间，同时避免缩到观众无法理解动作。

## 动画必须表达操作因果

不要让多个互不相关的 timeout 分别决定鼠标、输入、点击和页面切换。给关键动作设置可观察的前置条件：

```text
目标存在且布局稳定 → 鼠标到位 → 点击完成 → 输入获得演示焦点
→ 鼠标静止并输入 → 文本完成 → 移到发送按钮 → 点击 → 消息出现
```

链接预览则是：链接渲染完成 → 鼠标落在文字上 → 点击完成 → 打开内部预览标签。按 Enter 搜索时，鼠标可以留在已聚焦的搜索框中，不必伪造一次鼠标点击。

- 让鼠标发出到位事件；播放头在关键动作之前等待该事件，再进行点击、聚焦、输入或跳转。放慢速度、暂停恢复、掉帧后也应成立。
- 装饰性自动演示只绘制焦点和插入符，不抢走访问者真实键盘焦点。真正的交互沙盒再由用户操作驱动真实焦点。
- 精确点击文字链接时测量实际文本边界；全宽段落或 block 容器的中心经常落在空白处。坐标跨缩放或 iframe 边界时，先统一坐标系，并考虑鼠标尖端的位置。
- 输入期间不要重新寻路或随机漂移。目标暂时消失时先停留；需要推进的目标始终找不到时，应修复场景或明确进入失败/重置状态，不能通过超时直接假装点击成功。
- 手动重播和循环重启都清理到位标记、焦点、未完成移动和旧回调，重新建立目标。目标选择器没变化，也要避免旧的“已到位”状态污染下一轮或丢失新到位通知。

平滑移动可用轻微弧线、随距离变化的时长和起落缓速。重定向从当前绘制位置开始，取消旧动画后保留连续位置；点击以指针尖端为锚点做轻微反馈。使用统一时钟或可协调的动画生命周期，使暂停、离屏、页面隐藏与卸载能停止并清理相应动作。

多卡片的错落感来自不同启动延迟、操作速度和结果停留，而不是所有卡片同时清屏。优先使用可复现的节奏；随机性不能破坏操作顺序或让测试不可重复。为 reduced-motion 提供有意义的静态结果。

## 用行为证据验收

构建成功只证明代码能打包。到真正挂载的页面检查最终比例和完整过程；有 iframe、静态构建或缓存时，确认看到的是这次产物。

按 [动作与视觉验收](references/validation.md) 检查当前修改相关的边界。重点证明：

- 输入开始前已经聚焦，文字增加期间鼠标坐标不变。
- 点击瞬间指针位于真实目标内；结果在点击后出现。
- 暂停/恢复、重播、循环和视口缩放不会跳过必要动作。
- 状态、文件、消息、工具调用在可交互演示中互相一致。

交付说明只报告实际改动、已做验证和仍为模拟的边界。未做的端到端检查不要写成通过。

