Install
$ agentstack add skill-popmechanic-vibesos-design ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
> Plan mode: If you are planning work, this entire skill is ONE plan step: "Invoke /vibes:design". Do not decompose the steps below into separate plan tasks.
Display this ASCII art immediately when starting:
░▒▓███████▓▒░░▒▓████████▓▒░░▒▓███████▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓██████▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░
Design Reference Transformer
Transform a complete design reference HTML file into a working Vibes app with TinyBase reactive data.
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/TinyBase—not to recreate it from your understanding of its aesthetic.
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
The Transformation is Mechanical
The conversion from design HTML to React/TinyBase is deterministic, not creative:
| Transformation | Rule | Example | |----------------|------|---------| | Attributes | class → className | class="btn" → className="btn" | | Attributes | for → htmlFor | for="email" → htmlFor="email" | | Attributes | kebab-case → camelCase | stroke-width → strokeWidth | | Self-closing | Add explicit close | ` → | | Comments | HTML → JSX | → {/ x /} | | Inline styles | String → Object | style="color: red" → style={{ color: 'red' }} | | Event handlers | Lowercase → camelCase | onclick → onClick` |
CSS requires NO changes. Copy the entire `` block verbatim.
Workflow
Step 1: Read the Design Reference
# Read the design file completely
Read design.html
Note the structure:
- `` block (copy verbatim)
- HTML structure (preserve exactly)
- Any vanilla JavaScript (will be replaced with React)
Step 2: Identify Dynamic Content
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.
Step 3: Create the React Component
function App() {
// TinyBase hooks are globals — no imports, no initialization call needed
const rowIds = useRowIds('items');
const handleAdd = useAddRowCallback('items', (e) => ({
text: '', type: 'item', created: Date.now()
}));
return (
<>
{/* CSS copied VERBATIM from design.html */}
{`
/* Paste entire block here unchanged */
`}
{/* HTML structure preserved, only syntax converted */}
{/* Dynamic content replaced with {expressions} */}
);
}
Step 4: Handle Dark Mode Override (If Needed)
The Vibes template has dark mode support. If your design is light-only, add this CSS override:
/* 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.
Step 4b: Scope CSS to Avoid VibesSwitch/VibesPanel Conflicts
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:
| Problematic | Why | Safe Alternative | |-------------|-----|------------------| | button { ... } | Styles VibesSwitch toggle | .app button { ... } or #container button { ... } | | * { ... } (with colors/backgrounds) | Cascades everywhere | Scope to specific containers | | [style*="position: fixed"] | Targets VibesSwitch | Target by class/ID instead | | body > div | May match menu wrapper | Use #container > div |
If your design has global button/element styles:
- Wrap your app content in a container with a class:
... - Scope broad rules:
button { }→.app button { } - Or use
#containerwhich is the template's app root
The template already protects components with:
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.
Step 5: Assemble and Test
VIBES_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "${CLAUDE_SKILL_DIR}")")}"
bun "$VIBES_ROOT/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.
Anti-Patterns (DO NOT DO THESE)
| Anti-Pattern | Why It's Wrong | Correct Approach | |--------------|----------------|------------------| | Translate colors to OKLCH | Changes the design | Use exact hex values from reference | | Restructure HTML "for React" | Breaks layout | Preserve structure, only change syntax | | "Improve" the CSS | Not your job | Copy verbatim | | Add your own classes | Introduces drift | Use exact classes from reference | | Interpret the "vibe" | Creates divergence | Be literal, not interpretive | | Skip vanilla JS analysis | Miss functionality | Understand what it does, then React-ify |
Transformation Checklist
Before writing code, verify:
- [ ] Read the entire design.html file
- [ ] Identified all `` 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)
Example: Static List → Dynamic List
Design HTML:
First item
Second item
React with TinyBase:
const rowIds = useRowIds('items');
{rowIds.map(id => (
))}
// Child component uses useCell for reactive per-row data
function ItemRow({ id }) {
const text = useCell('items', id, 'text');
return {text};
}
Note: Only the content changed. The classes, structure, and styling are identical.
Example: Static Form → Controlled Form
Design HTML:
Submit
React with TinyBase:
const [text, setText] = useState('');
const handleAdd = useAddRowCallback('items', () => ({
text, type: 'item', created: Date.now()
}));
{ e.preventDefault(); handleAdd(); setText(''); }}>
setText(e.target.value)}
/>
Submit
Note: Same structure, same classes, same placeholder. Only added React bindings.
Integration with Vibes Assembly
This skill produces an app.jsx that works with the standard Vibes assembly:
# In the working directory
VIBES_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "${CLAUDE_SKILL_DIR}")")}"
bun "$VIBES_ROOT/scripts/assemble.js" app.jsx index.html
The assembly script:
- Inserts your JSX into the Vibes template
- Handles OIDC authentication wrapper (via Pocket ID)
- Sets up import maps for React and TinyBase
- Configures sync URLs if present (auth is automatic via Pocket ID)
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 Cloudflare (/cloudflare)"
Description: "Push the app live to Cloudflare Workers"
- Label: "Make adjustments"
Description: "Fine-tune specific elements while preserving the design"
- Label: "I'm done"
Description: "Wrap up - files are saved locally"
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: popmechanic
- Source: popmechanic/VibesOS
- License: MIT
- Homepage: https://install.vibesos.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.