npx claudepluginhub popmechanic/vibesos --plugin vibesThis skill is limited to using the following tools:
> **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.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
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:
░▒▓███████▓▒░░▒▓████████▓▒░░▒▓███████▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓██████▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░
Transform a complete design reference HTML file into a working Vibes app with TinyBase reactive data.
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.
Use this skill when:
design.html, mockup, or static prototype fileThe 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 | <input> → <input /> |
| Comments | HTML → JSX | <!-- x --> → {/* x */} |
| Inline styles | String → Object | style="color: red" → style={{ color: 'red' }} |
| Event handlers | Lowercase → camelCase | onclick → onClick |
CSS requires NO changes. Copy the entire <style> block verbatim.
# Read the design file completely
Read design.html
Note the structure:
<style> block (copy verbatim)Ask: "What content comes from the database?"
Typical dynamic elements:
.map())Everything else stays static.
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 */}
<style>{`
/* Paste entire <style> block here unchanged */
`}</style>
{/* HTML structure preserved, only syntax converted */}
{/* Dynamic content replaced with {expressions} */}
</>
);
}
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.
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:
<div className="app">...</div>button { } → .app button { }#container which is the template's app rootThe 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.
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-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 |
Before writing code, verify:
<style> blocks (will copy verbatim)During transformation:
{expressions} and .map()After assembly:
Design HTML:
<ul class="item-list">
<li class="item">First item</li>
<li class="item">Second item</li>
</ul>
React with TinyBase:
const rowIds = useRowIds('items');
<ul className="item-list">
{rowIds.map(id => (
<ItemRow key={id} id={id} />
))}
</ul>
// Child component uses useCell for reactive per-row data
function ItemRow({ id }) {
const text = useCell('items', id, 'text');
return <li className="item">{text}</li>;
}
Note: Only the content changed. The classes, structure, and styling are identical.
Design HTML:
<form>
<input type="text" class="input" placeholder="Enter text...">
<button class="btn">Submit</button>
</form>
React with TinyBase:
const [text, setText] = useState('');
const handleAdd = useAddRowCallback('items', () => ({
text, type: 'item', created: Date.now()
}));
<form onSubmit={(e) => { e.preventDefault(); handleAdd(); setText(''); }}>
<input
type="text"
className="input"
placeholder="Enter text..."
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button type="submit" className="btn">Submit</button>
</form>
Note: Same structure, same classes, same placeholder. Only added React bindings.
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:
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"