---
description: Generate a working HTML/JS prototype page and push it to launch-deck for click-through review. Use to validate behavior — flow, transitions, interactions — before any framework code is touched. Calls deck's rich-html block with framework=raw; supports CDN scripts, animations, real DOM events.
when_to_use: |
  Auto-fire when the user wants an INTERACTIVE throwaway page to validate behavior — click flows, transitions, optimistic updates, keyboard shortcuts, drag/drop — before any production code. Trigger phrases: "prototype X", "let me click through Y", "build a working demo of Z", "test the interaction for X", "throwaway version of W", "make it interactive so I can try it", "show me how the kanban drag would feel". Deck is required because the deliverable is a rendered, clickable page the user must touch — text/code descriptions in the terminal don't substitute. Do NOT auto-fire for: production implementation (use the appropriate fe:* / be:* flow), static visual mockups (use /kit:wireframe), reading or explaining existing code behavior (use /kit:analyse), plain-text walkthroughs of an interaction that the user can read in the terminal, or any request that's clearly about discussion not artifact production.
allowed-tools:
  - mcp__launch-deck__server_status
  - mcp__launch-deck__start_server
  - mcp__launch-deck__deck
  - mcp__launch-deck__await_feedback
  - mcp__launch-chart__read_graph
  - Bash
---

# /kit:prototype

Build a self-contained, interactive HTML page (HTML + CSS + JS, optional CDN scripts) and push it to launch-deck. Unlike `/kit:wireframe`, this is a *working* prototype: the user can click, type, navigate fake routes, see transitions — the goal is to test behavior cheaply.

Parse `$ARGUMENTS`:
- **description** (required) — what the prototype should demonstrate, e.g. "drag-to-reorder kanban with optimistic update and rollback on error".
- **--session=<id>** — deck session name. Default `proto-<slugified-description-first-3-words>`.
- **--feedback** — push in `feedback` mode with `prompt: "Did this match the interaction you had in mind?"` and call `await_feedback`.
- **--cdn=tailwind|alpine|htmx|react|vue|none** — comma-separated CDN(s) to include. Default `tailwind` for styling. `none` for pure handwritten CSS.
- **--theme=light|dark** — only when the prototype demands one mode (e.g. a dark-mode-only design).

Examples:
- `/kit:prototype drag-to-reorder kanban with optimistic update`
- `/kit:prototype keyboard shortcut palette with fuzzy search --cdn=tailwind,alpine`
- `/kit:prototype landing page hero with parallax scroll --feedback`

## Preflight

1. Confirm `mcp__launch-deck__server_status` is running. Start if not.
2. If the description references real entities/pages in this repo, run `mcp__launch-chart__read_graph(search: <hint>)` to pull the shape — so the prototype mirrors actual data field names. Optional; skip on first iteration to keep the loop fast.

## Build the page

Generate a complete `<!DOCTYPE html>` document. Layout:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title><short title></title>
  <!-- CDNs (per --cdn flag) -->
  <script src="https://cdn.tailwindcss.com"></script>
  <script defer src="https://unpkg.com/alpinejs"></script>
  <style>
    /* page-specific styles */
  </style>
</head>
<body class="…">
  <!-- the prototype -->
  <script>
    // event handlers, state, fake data
  </script>
</body>
</html>
```

CDN catalog (use only what's requested):
- **tailwind** — `<script src="https://cdn.tailwindcss.com"></script>`
- **alpine** — `<script defer src="https://unpkg.com/alpinejs"></script>` for `x-data` reactivity
- **htmx** — `<script src="https://unpkg.com/htmx.org"></script>` for fake server swaps
- **react** — `<script crossorigin src="https://unpkg.com/react/umd/react.production.min.js"></script>` + `react-dom` + Babel CDN if JSX
- **vue** — `<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>`

Design rules:
- **Fake the backend.** Use in-memory arrays, `setTimeout` to simulate latency, `Math.random() < 0.1` to simulate intermittent failures (for testing rollback flows).
- **No real PII or secrets.** Use placeholder names ("Ada", "Lin", "Mehmet"), placeholder copy, never a real user from this project.
- **Show the interaction explicitly.** If the prototype's point is drag-to-reorder, make the drag affordance OBVIOUS (cursor change, hover scale, snap line). If the point is optimistic update + rollback, force a visible failure within ~5 clicks so the reviewer experiences it.
- **One screen unless the user asks for multi-screen.** Multi-screen prototypes use a fake router (`window.history.pushState` + a click handler) — don't pull in `react-router`.

## Push to deck

Call `mcp__launch-deck__deck` with:
- `session: <session>`
- `mode: "show"` or `"feedback"` (+ `prompt`)
- `blocks: [{ type: "rich-html", framework: "raw", label: <short-title>, content: <full-doctype-html>, theme: <theme?> }]`

`framework: "raw"` means the deck does NOT wrap your content — what you ship IS the page. That's why the full `<!DOCTYPE html>` doctype is required.

If `--feedback`, call `mcp__launch-deck__await_feedback` afterward and surface the response.

## Open in browser

After the push (and after `await_feedback` if `--feedback`), open the per-session URL so the user lands directly on this prototype:

```
open "<deck-url>/#<session>"          # macOS
xdg-open "<deck-url>/#<session>"      # Linux
```

`<deck-url>` is the `url` returned by `mcp__launch-deck__server_status` (typically `http://localhost:52829`). The `#<session>` hash deep-links to this exact session.

## Output

```
prototype pushed — deck session "<session>" — <deck-url>/#<session>
size: <N> KB markup, <M> CDN scripts, <K> inline event handlers
demonstrates: <one-line>
```

## Constraints

- **Self-contained.** No external API calls, no auth flows, no real LS endpoints. Everything in one HTML file.
- **One block per push.** Multi-block prototypes belong as separate sessions.
- **Iterate via re-push.** Same `--session` overwrites — that's the loop. Don't accumulate prototype-v2, prototype-v3 sessions.
- **No production-ready output.** If the user is happy with the prototype and wants to "turn it into the real thing," that's a separate `/fe:*` workflow — this skill is throw-away to validate behavior.
