Ivan's Blog
主题

Web demo

Web demo 表示仓库刻意提供一个可直接给 owner、评审者或潜在用户体验的 Web 演示面,而且这个演示面复用正式产品前端与正式路由,而不是单独做一套只用于截图的 demo 页面。它允许用 mock backend、simulation device、read-only seed data 或等价安全输入来稳定复现产品行为,但默认不要求接入真实生产登录、真实后端写路径或真实硬件危险写操作。

  • 前端

目录

Definition

Web demo 表示仓库刻意提供一个可直接给 owner、评审者或潜在用户体验的 Web 演示面,而且这个演示面复用正式产品前端与正式路由,而不是单独做一套只用于截图的 demo 页面。它允许用 mock backend、simulation device、read-only seed data 或等价安全输入来稳定复现产品行为,但默认不要求接入真实生产登录、真实后端写路径或真实硬件危险写操作。

这个 Topic 的核心不是“页面能打开”,而是“演示面本身就是产品 surface 的受控子集”。成熟实现把 live app 和 demo 当作同源但不同运行时:共用 App 树、正式 route suffix、视觉组件和 API 调用面;live runtime 连接真实认证/后端,demo runtime 则在渲染前启动 mock interception、模拟身份和内存状态。它不是在生产 live bundle 上留一个任意 query 开关,也不是为了验收复制一份页面。

当 demo 需要承担页面级证据、交互验收或方案评审时,结构化 Inspector/控制面板也是 contract 的一部分:它应让审查者明确控制 scene、persona/权限、network fault、数据开关、simulated action 和 share state,并在不同视口下既可审查又不遮蔽正式布局。raw JSON 可保留为高级入口,但不应成为主操作面(projects/octo-rill.md)。

When to use

当项目需要一个浏览器里的 owner-facing 或 public-facing 演示入口,并且这个入口满足以下事实时使用:

  • 演示面复用正式前端代码与正式路由,不是额外拼出来的独立样板页。
  • 演示面可以通过 mock、simulation 或 read-only seed 安全运行,不依赖真实生产写操作。
  • 演示面被设计成可直接体验产品行为,而不是只用于组件 QA、内容阅读或本地开发联调。
  • 页面、流程或安全写入链路需要稳定的视觉证据、可分享复现状态,且真实后端/设备不应参与验收。
  • 项目同时维护真实后端 runtime 与 mock runtime,并希望两者长期复用同一产品 UI、route 与 transport contract。

如果仓库只有 docs-site / public content site、只有 Storybook component QA、或只有普通 preview 服务,而没有正式产品 surface 的受控演示 contract,就不要打这个标签。若目标只是临时测试某个组件或修一个局部 mock,也不应为此引入完整 Web demo;这类工作仍属于 Storybook、fixture 或 e2e helper 的职责。

Habits / defaults

  • 演示面优先复用正式路由和正式状态模型。loadlynx 的 simulation device 走真实设备页面与控制台逻辑,mains-aegis 在 PRODUCT.md 里直接要求 testable example 复用正式 frontend 与正式 route,而不是另做一套说明页(projects/loadlynx.md、projects/mains-aegis.md)。
  • 演示输入优先走 mock / simulation / read-only seed,而不是伪静态截图。loadlynx 的 mock backend 与 simulation device、mains-aegis 的 mock-seeded interactive direct-access path,都说明“能交互的安全假数据”比“看图说话”更接近正确做法(projects/loadlynx.md、projects/mains-aegis.md)。
  • 危险写操作默认关闭、降级或延后。mains-aegis 把首版 Web 管理界面明确限定为只读 UPS 运维控制台;Web demo 也应默认把真实硬件写入、生产控制或高风险动作排除在演示 contract 之外(projects/mains-aegis.md)。
  • 将 live / demo 视为显式运行时边界,而非“真实 App 加几个 if”。Demo bootstrap 必须在认证 bootstrap、初始数据请求和实时流订阅之前完成 mock worker 启动;worker 失败时应停止 App 渲染并给出安全错误面,不能回退到真实 API(projects/octo-rill.md)。
  • 为 demo 提供独立 build target 和公开子路径,保持 docs-site 或正常 App 根路径不变。公开静态托管还要为 /demo/** 配置深链恢复;demo=<scene-id> 只选择 mock scene,d_* 用于分享 persona、network、数据等可复现状态,避免与正式产品 URL 参数冲突(projects/octo-rill.md)。
  • 所有 demo 写操作都只更新 in-memory mock model,并立即在正式 UI 回显;控制面板要明确标记 simulated,并保留近期 mutation 记录。不要在 mock UI 回显输入的 secret 前缀或把 demo action 透传到真实服务(projects/octo-rill.md)。
  • 控制面板默认给出结构化字段:scene、persona/权限、network、data、actions、share。宽屏在不挤压 App 最大版心时可固定为全高左 rail,但必须能收起成 bubble;普通桌面使用有安全边界的浮层,移动端采用 bubble 到 drawer。面板布局 local-only,产品场景状态 URL-first(projects/octo-rill.md)。
  • 页面/流程证据优先由 mock-only ui_demo 产出;Storybook 继续承担可复用 Inspector/UI fragment 的 docs、canvas 和 interaction coverage,不能替代完整页面验收(projects/octo-rill.md)。
  • 演示面可以是公开 Pages、owner-facing hosted surface 或可控 handoff URL,但“能部署”不自动等于 Web demo。只有当它承担正式产品行为演示职责,并复用正式 app surface,才应纳入这个 Topic(projects/isolappurr-usb-hub.md、projects/loadlynx.md)。
  • Storybook、docs-site 和普通 preview 仍各有职责,但默认不是 Web demo 的替代品:Storybook 负责组件状态 QA,docs-site 负责内容与说明,preview 负责本地运行验证;只有正式演示 contract 才属于本 Topic。

Reference implementations

  • projects/loadlynx.md:正式 Web UI 提供 simulation device、mock backend 与 production-mode demo 约束,让 owner 可以在不接真实硬件的情况下走真实设备路由和界面行为。
  • projects/isolappurr-usb-hub.md:GitHub Pages 承载 React SPA 演示面,复用正式 dashboard/device routes,并通过 Base URL / PNA / 局域网设备接入保持“真实产品 UI + 受控设备连接”的体验。
  • projects/mains-aegis.md:PRODUCT.md 把 direct-access demo path 定义为复用正式 frontend/routes 的 mock-seeded 交互示例,同时坚持 Web 首版只读,避免把危险控制路径混进演示面。
  • projects/octo-rill.md:将 /demo/ 构建成公开 mock-only 子应用,在同一 React App 树内把 MSW、SSE 适配、scene registry 和 in-memory simulated writes 前置到认证之前;Inspector 同时覆盖宽屏 pinned rail、浮层和移动 drawer,因此适合作为“证据控制面板不应破坏产品布局”的参考实现。

这四类实现的共同点是:演示面不是 docs 或组件画廊,而是正式产品 surface 的安全演示形态。它们也共同说明,Web demo 可以公开托管,也可以只给 owner 使用;决定因素不是发布渠道,而是是否复用正式 app contract 并提供稳定可体验的 mock/simulation/read-only 路径。

Failure modes

  • 把 docs-site / public content site 直接当成 Web demo,会让后续 Agent 误以为内容站已经覆盖了产品交互演示。
  • 把 Storybook component QA / Storybook accessibility 当成 Web demo,会把组件级状态验证误升级为产品级演示能力。
  • 把普通本地 preview 服务当成 owner-facing handoff,导致演示入口依赖开发环境而不是稳定的正式 surface contract。
  • 为了 demo 单独复制一套页面或路由,结果演示面和正式产品行为分叉;这样即使“能演示”,也不再是这个 Topic 要保留的正确做法。
  • 在 demo 模式里保留真实写操作、真实硬件危险控制或生产态破坏性入口,会让演示面失去“安全可复现”的前提。
  • 先渲染 App、后启动 mock worker,或 worker 启动失败后继续降级到 live fetch,会造成认证/API 泄漏;把 mock interception 变成 bootstrap 前置条件才能避免这种隐性越界。
  • 让 Inspector 只在大屏永久占宽、或仅作为不可避让的浮层,会破坏两种审查目标:前者不能回看正常布局,后者会遮蔽交互和溢出视口。面板必须同时有 layout-aware dock/floating/drawer 和可恢复的 bubble 状态。
  • 面板控制通过 location.href 或完整 document reload 更新 scene,会重置 App 并掩盖真实状态同步问题。场景和 share state 变更应走 client-side navigation 与运行时状态同步。
  • 公开 /demo/** 没有静态 404 recovery 时,复制的深链在刷新后会落到文档 404;只验证 demo root 不能证明分享入口可用。
  • 把 Storybook 截图当作最终页面证据,会遗漏路由、认证 bootstrap、mock transport、写入回显和响应式面板之间的组合问题。

Evidence index

  • projects/loadlynx.md
  • projects/isolappurr-usb-hub.md
  • projects/mains-aegis.md
  • projects/octo-rill.md
  • skills/style-playbook/references/data/topics/web-demo.json
  • skills/style-web-demo/SKILL.md