design-reference

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Plan mode: If you are planning work, this entire skill is ONE plan step: "Invoke /vibes:design-reference". Do not decompose the steps below into separate plan tasks.
Display this ASCII art immediately when starting:
░▒▓███████▓▒░░▒▓████████▓▒░░▒▓███████▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓██████▓▒░  ░▒▓██████▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░             ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░             ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░
计划模式:如果你正在规划工作,整个技能仅作为一个计划步骤:"调用 /vibes:design-reference"。不要将以下步骤拆分为单独的计划任务。
开始时立即显示此ASCII图案:
░▒▓███████▓▒░░▒▓████████▓▒░░▒▓███████▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓██████▓▒░  ░▒▓██████▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░             ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░             ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░

Design Reference Transformer

设计参考转换工具

Transform a complete design reference HTML file into a working Vibes app with Fireproof data persistence.

将完整的设计参考HTML文件转换为带有Fireproof数据持久化功能的可运行Vibes应用。

Core Principle

核心原则

Preserve and adapt, don't interpret and recreate.
The design reference is source code to transform, not inspiration to interpret. When given a complete HTML file with styles, your job is to make minimal surgical changes to connect it to React/Fireproof—not to recreate it from your understanding of its aesthetic.

保留并适配,而非解读与重造。
设计参考是待转换的源代码,而非用于解读的灵感来源。当收到包含样式的完整HTML文件时,你的工作是进行最小化的精准修改以将其连接到React/Fireproof——而非根据你对其美学的理解重造它。

When to Use This Skill

何时使用此技能

Use this skill when:
  • User provides a
    design.html
    , mockup, or static prototype file
  • User says "match this design exactly" or "use this as a reference"
  • User wants their existing HTML converted to a Vibes app
  • A previous implementation didn't match the design reference

在以下场景使用此技能:
  • 用户提供
    design.html
    、模型或静态原型文件
  • 用户表示“完全匹配此设计”或“以此为参考”
  • 用户希望将现有HTML转换为Vibes应用
  • 之前的实现未匹配设计参考

The Transformation is Mechanical

转换过程是机械性的

The conversion from design HTML to React/Fireproof is deterministic, not creative:
TransformationRuleExample
Attributes
class
className
class="btn"
className="btn"
Attributes
for
htmlFor
for="email"
htmlFor="email"
Attributeskebab-case → camelCase
stroke-width
strokeWidth
Self-closingAdd explicit close
<input>
<input />
CommentsHTML → JSX
<!-- x -->
{/* x */}
Inline stylesString → Object
style="color: red"
style={{ color: 'red' }}
Event handlersLowercase → camelCase
onclick
onClick
CSS requires NO changes. Copy the entire
<style>
block verbatim.

从设计HTML到React/Fireproof的转换是确定性的,而非创造性的
转换操作规则示例
属性
class
className
class="btn"
className="btn"
属性
for
htmlFor
for="email"
htmlFor="email"
属性短横线命名 → 驼峰命名
stroke-width
strokeWidth
自闭合标签添加显式闭合
<input>
<input />
注释HTML → JSX
<!-- x -->
{/* x */}
内联样式字符串 → 对象
style="color: red"
style={{ color: 'red' }}
事件处理器小写 → 驼峰命名
onclick
onClick
CSS无需修改。 完整复制
<style>
块内容。

Workflow

工作流程

Step 1: Read the Design Reference

步骤1:读取设计参考

bash
undefined
bash
undefined

Read the design file completely

完整读取设计文件

Read design.html

Note the structure:
- `<style>` block (copy verbatim)
- HTML structure (preserve exactly)
- Any vanilla JavaScript (will be replaced with React)
Read design.html

注意以下结构:
- `<style>`块(原样复制)
- HTML结构(完全保留)
- 任何原生JavaScript(将被React替代)

Step 2: Identify Dynamic Content

步骤2:识别动态内容

Ask: "What content comes from the database?"
Typical dynamic elements:
  • List items that repeat (
    .map()
    )
  • Text that users enter (controlled inputs)
  • Counts, totals, timestamps
  • User-specific content
Everything else stays static.
思考:“哪些内容来自数据库?”
典型的动态元素:
  • 重复的列表项(使用
    .map()
  • 用户输入的文本(受控输入框)
  • 计数、总计、时间戳
  • 用户专属内容
其他所有内容保持静态。

Step 3: Create the React Component

步骤3:创建React组件

jsx
import React from "react";
import { useFireproofClerk } from "use-fireproof";

export default function App() {
  const { database, useLiveQuery, useDocument } = useFireproofClerk("app-db");

  // Hooks for dynamic data
  const { doc, merge, submit } = useDocument({ /* initial shape */ });
  const { docs } = useLiveQuery("type", { key: "item" });

  return (
    <>
      {/* CSS copied VERBATIM from design.html */}
      <style>{`
        /* Paste entire <style> block here unchanged */
      `}</style>

      {/* HTML structure preserved, only syntax converted */}
      {/* Dynamic content replaced with {expressions} */}
    </>
  );
}
jsx
import React from "react";
import { useFireproofClerk } from "use-fireproof";

export default function App() {
  const { database, useLiveQuery, useDocument } = useFireproofClerk("app-db");

  // 动态数据钩子
  const { doc, merge, submit } = useDocument({ /* 初始结构 */ });
  const { docs } = useLiveQuery("type", { key: "item" });

  return (
    <>
      {/* 从design.html原样复制的CSS */}
      <style>{`
        {/* 在此处粘贴完整的<style>块内容,不做修改 */}
      `}</style>

      {/* HTML结构保留,仅转换语法 */}
      {/* 动态内容替换为{表达式} */}
    </>
  );
}

Step 4: Handle Dark Mode Override (If Needed)

步骤4:处理深色模式覆盖(如需)

The Vibes template has dark mode support. If your design is light-only, add this CSS override:
css
/* Force light theme regardless of system preference */
html, body, #container, #container > div {
    background-color: var(--your-bg-color) !important;
}
Note: Avoid targeting
[style*="position: fixed"]
as this will style the VibesSwitch toggle button.
Vibes模板支持深色模式。若你的设计仅支持浅色模式,添加以下CSS覆盖:
css
/* 强制使用浅色主题,不受系统偏好设置影响 */
html, body, #container, #container > div {
    background-color: var(--your-bg-color) !important;
}
注意: 避免定位
[style*="position: fixed"]
,这会影响VibesSwitch切换按钮的样式。

Step 4b: Scope CSS to Avoid VibesSwitch/VibesPanel Conflicts

步骤4b:限定CSS作用域以避免与VibesSwitch/VibesPanel冲突

The template includes a VibesSwitch toggle button and VibesPanel admin menu that sit outside your app container. Broad CSS selectors can accidentally style these components.
Watch for these problematic patterns:
ProblematicWhySafe Alternative
button { ... }
Styles VibesSwitch toggle
.app button { ... }
or
#container button { ... }
* { ... }
(with colors/backgrounds)
Cascades everywhereScope to specific containers
[style*="position: fixed"]
Targets VibesSwitchTarget by class/ID instead
body > div
May match menu wrapperUse
#container > div
If your design has global button/element styles:
  1. Wrap your app content in a container with a class:
    <div className="app">...</div>
  2. Scope broad rules:
    button { }
    .app button { }
  3. Or use
    #container
    which is the template's app root
The template already protects components with:
css
button[aria-controls="hidden-menu"] { background: transparent !important; }
#hidden-menu { /* menu-specific variable resets */ }
But defense-in-depth is better—scope your CSS to avoid conflicts.
模板包含VibesSwitch切换按钮和VibesPanel管理菜单,它们位于应用容器外部。宽泛的CSS选择器可能会意外影响这些组件的样式。
注意以下有问题的模式:
有问题的写法原因安全替代方案
button { ... }
会样式化VibesSwitch切换按钮
.app button { ... }
#container button { ... }
* { ... }
(涉及颜色/背景)
会全局级联限定到特定容器
[style*="position: fixed"]
会定位VibesSwitch改用类名/ID定位
body > div
可能匹配菜单容器使用
#container > div
若你的设计包含全局按钮/元素样式:
  1. 将应用内容包裹在带类名的容器中:
    <div className="app">...</div>
  2. 限定宽泛规则的作用域:
    button { }
    .app button { }
  3. 或使用模板的应用根容器
    #container
模板已通过以下方式保护组件:
css
button[aria-controls="hidden-menu"] { background: transparent !important; }
#hidden-menu { /* 菜单专属变量重置 */ }
但多层防御更稳妥——限定你的CSS作用域以避免冲突。

Step 5: Assemble and Test

步骤5:组装与测试

bash
node "/path/to/vibes-skill/scripts/assemble.js" app.jsx index.html
Open in browser and visually diff against the design reference. They should be pixel-identical except for dynamic content.

bash
node "/path/to/vibes-skill/scripts/assemble.js" app.jsx index.html
在浏览器中打开并与设计参考进行视觉对比。除动态内容外,两者应像素级一致。

Anti-Patterns (DO NOT DO THESE)

反模式(切勿执行)

Anti-PatternWhy It's WrongCorrect Approach
Translate colors to OKLCHChanges the designUse exact hex values from reference
Restructure HTML "for React"Breaks layoutPreserve structure, only change syntax
"Improve" the CSSNot your jobCopy verbatim
Add your own classesIntroduces driftUse exact classes from reference
Interpret the "vibe"Creates divergenceBe literal, not interpretive
Skip vanilla JS analysisMiss functionalityUnderstand what it does, then React-ify

反模式错误原因正确做法
将颜色转换为OKLCH会改变设计使用参考文件中的精确十六进制值
为适配React重构HTML会破坏布局保留结构,仅修改语法
“优化”CSS这不是你的工作原样复制
添加自定义类名会导致设计偏差使用参考文件中的精确类名
解读设计的“风格”会产生差异严格按字面转换,不做解读
跳过原生JavaScript分析会遗漏功能先理解其功能,再转换为React实现

Transformation Checklist

转换检查清单

Before writing code, verify:
  • Read the entire design.html file
  • Identified all
    <style>
    blocks (will copy verbatim)
  • Identified dynamic content (lists, inputs, user data)
  • Identified vanilla JS functionality (will convert to React)
  • Noted any custom fonts (add to imports if needed)
  • Checked for dark/light theme assumptions
During transformation:
  • CSS pasted unchanged (no "improvements")
  • HTML structure preserved exactly
  • Only syntax converted (class→className, etc.)
  • Dynamic content uses
    {expressions}
    and
    .map()
  • Vanilla JS replaced with React hooks and handlers
  • Dark mode override added if design is light-only
After assembly:
  • Visual comparison with design reference
  • All interactive elements work
  • Data persists on refresh
  • No console errors
  • VibesSwitch toggle (bottom-right) displays correctly with no background box
  • VibesPanel menu opens when toggle is clicked
  • Menu buttons are correctly styled (not inheriting app button styles)

编写代码前,确认:
  • 已完整阅读design.html文件
  • 已识别所有
    <style>
    块(将原样复制)
  • 已识别动态内容(列表、输入框、用户数据)
  • 已识别原生JavaScript功能(将转换为React实现)
  • 已记录任何自定义字体(如需添加至导入)
  • 已检查深色/浅色主题预设
转换过程中:
  • CSS已原样粘贴(无“优化”)
  • HTML结构已完全保留
  • 仅转换语法(class→className等)
  • 动态内容使用
    {表达式}
    .map()
  • 原生JavaScript已替换为React钩子和处理函数
  • 若设计仅支持浅色模式,已添加深色模式覆盖
组装完成后:
  • 与设计参考进行视觉对比
  • 所有交互元素可正常工作
  • 刷新后数据可持久化
  • 控制台无错误
  • VibesSwitch切换按钮(右下角)显示正常,无背景框
  • 点击切换按钮可打开VibesPanel管理菜单
  • 菜单按钮样式正确(未继承应用按钮样式)

Example: Static List → Dynamic List

示例:静态列表 → 动态列表

Design HTML:
html
<ul class="item-list">
  <li class="item">First item</li>
  <li class="item">Second item</li>
</ul>
React with Fireproof:
jsx
const { docs } = useLiveQuery("type", { key: "item" });

<ul className="item-list">
  {docs.map(item => (
    <li key={item._id} className="item">{item.text}</li>
  ))}
</ul>
Note: Only the content changed. The classes, structure, and styling are identical.

设计HTML:
html
<ul class="item-list">
  <li class="item">First item</li>
  <li class="item">Second item</li>
</ul>
搭配Fireproof的React实现:
jsx
const { docs } = useLiveQuery("type", { key: "item" });

<ul className="item-list">
  {docs.map(item => (
    <li key={item._id} className="item">{item.text}</li>
  ))}
</ul>
注意:仅内容发生变化。类名、结构和样式完全一致。

Example: Static Form → Controlled Form

示例:静态表单 → 受控表单

Design HTML:
html
<form>
  <input type="text" class="input" placeholder="Enter text...">
  <button class="btn">Submit</button>
</form>
React with Fireproof:
jsx
const { doc, merge, submit } = useDocument({ text: "", type: "item" });

<form onSubmit={submit}>
  <input
    type="text"
    className="input"
    placeholder="Enter text..."
    value={doc.text}
    onChange={(e) => merge({ text: e.target.value })}
  />
  <button type="submit" className="btn">Submit</button>
</form>
Note: Same structure, same classes, same placeholder. Only added React bindings.

设计HTML:
html
<form>
  <input type="text" class="input" placeholder="Enter text...">
  <button class="btn">Submit</button>
</form>
搭配Fireproof的React实现:
jsx
const { doc, merge, submit } = useDocument({ text: "", type: "item" });

<form onSubmit={submit}>
  <input
    type="text"
    className="input"
    placeholder="Enter text..."
    value={doc.text}
    onChange={(e) => merge({ text: e.target.value })}
  />
  <button type="submit" className="btn">Submit</button>
</form>
注意:结构、类名、占位文本均相同。仅添加了React绑定。

Integration with Vibes Assembly

与Vibes组装工具的集成

This skill produces an
app.jsx
that works with the standard Vibes assembly:
bash
undefined
此技能生成的
app.jsx
可与标准Vibes组装工具配合使用:
bash
undefined

In the working directory

在工作目录中执行

node "/path/to/vibes-skill/scripts/assemble.js" app.jsx index.html

The assembly script:
- Inserts your JSX into the Vibes template
- Handles Clerk authentication wrapper
- Sets up import maps for React and Fireproof
- Configures Connect if `.env` is present

---
node "/path/to/vibes-skill/scripts/assemble.js" app.jsx index.html

组装脚本会:
- 将你的JSX插入Vibes模板
- 处理Clerk认证包装
- 为React和Fireproof设置导入映射
- 若存在`.env`文件则配置Connect

---

What's Next?

下一步操作?

After transforming a design reference, present these options using AskUserQuestion:
Question: "Design reference transformed! What's next?"
Header: "Next"
Options:
- Label: "Test locally"
  Description: "Open index.html in browser to verify it matches the design exactly"

- Label: "Deploy to exe.dev (/exe)"
  Description: "Push the app live at yourapp.exe.xyz"

- Label: "Make adjustments"
  Description: "Fine-tune specific elements while preserving the design"

- Label: "I'm done"
  Description: "Wrap up - files are saved locally"
完成设计参考转换后,使用AskUserQuestion呈现以下选项:
Question: "Design reference transformed! What's next?"
Header: "Next"
Options:
- Label: "Test locally"
  Description: "Open index.html in browser to verify it matches the design exactly"

- Label: "Deploy to exe.dev (/exe)"
  Description: "Push the app live at yourapp.exe.xyz"

- Label: "Make adjustments"
  Description: "Fine-tune specific elements while preserving the design"

- Label: "I'm done"
  Description: "Wrap up - files are saved locally"