Help us improve
Share bugs, ideas, or general feedback.
From playground-skill
Creates self-contained interactive HTML playgrounds with controls, live previews, and copyable prompts for visual exploration of design, data, code, and documents.
npx claudepluginhub stevysmith/playground-sync --plugin playground-skillHow this skill is triggered — by the user, by Claude, or both
Slash command
/playground-skill:playgroundThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A playground is a self-contained HTML file with interactive controls on one side, a live preview on the other, and a prompt output at the bottom with a copy button. The user adjusts controls, explores visually, then copies the generated prompt back into Claude.
Generates self-contained HTML playgrounds with controls, live previews, and copyable prompts for interactive exploration of design, data, code review, and architecture topics.
Create HTML playgrounds with sliders, knobs, toggles, and live preview for tuning algorithm parameters, animation values, design tokens, layout dimensions, or any value that's painful to express in text. Always include a Submit button (calls `submitToClaude`) so chosen values can be sent back to Claude Code. Use whenever the user wants to experiment with values, fine-tune behaviors, explore a parameter space, or pick from a continuous range — debounce timings, color values, easing curves, threshold values, layout dimensions, anything tunable.
Generates interactive, semantic HTML prototypes for human+AI agent use with Tailwind+DaisyUI (Tier A) or React+shadcn/ui+Vite (Tier B). Includes Playwright previews for iteration.
Share bugs, ideas, or general feedback.
A playground is a self-contained HTML file with interactive controls on one side, a live preview on the other, and a prompt output at the bottom with a copy button. The user adjusts controls, explores visually, then copies the generated prompt back into Claude.
When the user asks for an interactive playground, explorer, or visual tool for a topic — especially when the input space is large, visual, or structural and hard to express as plain text.
templates/:
templates/design-playground.md — Visual design decisions (components, layouts, spacing, color, typography)templates/data-explorer.md — Data and query building (SQL, APIs, pipelines, regex)templates/concept-map.md — Learning and exploration (concept maps, knowledge gaps, scope mapping)templates/document-critique.md — Document review (suggestions with approve/reject/comment workflow)templates/diff-review.md — Code review (git diffs, commits, PRs with line-by-line commenting)templates/code-map.md — Codebase architecture (component relationships, data flow, layer diagrams)open <filename>.html to launch it in the user's default browser.playground_watch MCP tool to wait for the user to click "Send to Claude". Tell the user you're watching for their prompt. When a prompt arrives, act on it, call playground_clear, and then call playground_watch again to wait for the next prompt. Repeat this loop indefinitely — every completed request should end with another playground_watch call so the user can keep sending prompts without restarting.localhost:4242. Falls back gracefully if no server is running. Include the transport snippet (see below).Keep a single state object. Every control writes to it, every render reads from it.
const state = { /* all configurable values */ };
function updateAll() {
renderPreview(); // update the visual
updatePrompt(); // rebuild the prompt text
}
// Every control calls updateAll() on change
function updatePrompt() {
const parts = [];
// Only mention non-default values
if (state.borderRadius !== DEFAULTS.borderRadius) {
parts.push(`border-radius of ${state.borderRadius}px`);
}
// Use qualitative language alongside numbers
if (state.shadowBlur > 16) parts.push('a pronounced shadow');
else if (state.shadowBlur > 0) parts.push('a subtle shadow');
prompt.textContent = `Update the card to use ${parts.join(', ')}.`;
}
Every playground must include this snippet alongside the copy button. It enables the "Send to Claude" button which posts the prompt to a local sync server. If the server isn't running, the button shows "No server" briefly and the user can still copy-paste.
<button id="send-btn" onclick="sendToClaude()">Send to Claude</button>
const SYNC_URL = 'http://localhost:4242';
async function sendToClaude() {
const prompt = document.getElementById('prompt-output').textContent;
const btn = document.getElementById('send-btn');
btn.textContent = 'Sending...';
try {
await fetch(SYNC_URL + '/prompt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt, url: location.href, pathname: location.pathname })
});
btn.textContent = 'Sent ✓';
setTimeout(() => btn.textContent = 'Send to Claude', 2000);
} catch {
btn.textContent = 'No server';
setTimeout(() => btn.textContent = 'Send to Claude', 3000);
}
}
try {
const es = new EventSource(SYNC_URL + '/events');
es.addEventListener('status', e => {
const d = JSON.parse(e.data);
const btn = document.getElementById('send-btn');
if (d.status === 'processing') btn.textContent = 'Claude working...';
if (d.status === 'done') { btn.textContent = 'Done ✓'; setTimeout(() => btn.textContent = 'Send to Claude', 2000); }
});
} catch {}