agentsclimarketplace

Interactive spec

Skill roeibh/interactive-spec

Turn written specs into self-contained interactive HTML mockups with a closed feedback loop back to Claude Code. A Claude skill.

Install
npx -y skills add roeibh/interactive-spec

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Generate a self-contained interactive HTML artifact from a spec, plan, or PRD so the developer can click through it, comment inline on any component or section, and submit those comments back to Claude — turning the HTML into a closed review loop, not a one-shot mockup. Use this skill whenever the user has just finished brainstorming a feature, has a spec or plan committed to `docs/superpowers/specs/` or `docs/superpowers/plans/`, mentions specs, plans, PRDs, design docs, requirements, mockups, or wireframes, says things like "make this concrete", "let me see it", "visualize the spec", "build a prototype of this", "turn this into a mockup", wants to review or iterate on a spec, or returns with a `feedback.json` or pasted feedback payload from a previously generated interactive spec. Especially use this right after `brainstorming` produces a design doc — offer it proactively then. Also triggers when the user says just "submitted", "feedback ready", "feedback sent", "applied", or similar short messages indicating they pushed feedback from the browser — in that case, check `~/.claude/interactive-spec-feedback/` for the most recent JSON file and consume it. Triggers for UI features (renders a clickable UI mockup) and non-UI features like backend, data pipelines, or algorithms (renders an interactive concept diagram or API explorer). Also triggers when the user pastes back a feedback bundle or drops a feedback.json. Don't undertrigger — if the user has a written spec and is about to implement, or is bringing feedback back from a review, this skill almost always belongs.

SKILL.md

20.7 KB, as published. Nobody here has run it

Interactive Spec

Turn a written spec into a self-contained interactive HTML artifact that is the spec — not a viewer of it. The developer opens the HTML, clicks through it, leaves comments anchored to specific elements, and submits those comments back to Claude. Claude reads the feedback and updates the spec and/or the HTML. Repeat until the spec is solid.

The HTML is generated alongside the spec markdown and lives in the repo as a first-class artifact. The feedback loop turns a static spec into a live review surface that Claude and the human can iterate on together.

This skill is the persistent counterpart to brainstorming's ephemeral visual-companion. Brainstorming uses HTML during the conversation to drive decisions; this skill emits an artifact after the spec is committed, lives next to the spec, and supports a structured comment-and-submit feedback loop that survives session boundaries.

Two Phases

This skill has two distinct phases. The user's request determines which.

  • Generate phase — produce a fresh interactive HTML from a spec or plan markdown.
  • Consume-feedback phase — apply a feedback.json (or pasted feedback payload, or a freshly-saved file in ~/.claude/interactive-spec-feedback/) by updating the spec markdown and/or regenerating relevant parts of the HTML.

Detect which phase by the input:

  • Has the user provided a spec/plan path with no feedback? → Generate.
  • Has the user pasted a JSON payload that starts with "feedback_session", dropped a *-feedback.json file, or said anything like "here's the feedback from the mockup"? → Consume-feedback.
  • Did the user say just "submitted", "feedback ready", "feedback sent", "applied", or a similarly short trigger? → Consume-feedback from ~/.claude/interactive-spec-feedback/ (see § Consuming via the optional server below).
  • Both at once? Generate first if no HTML exists yet, then immediately apply the feedback.

Generate Phase

1. Locate and read the source

  • If the user names a file, read it. Otherwise check docs/superpowers/specs/ and docs/superpowers/plans/ for the most recent.
  • Read the entire spec. Note: feature name, what's being built, user-facing surfaces, data shapes, key flows, open questions.

2. Classify the spec

Decide which mode fits:

  • UI mode — the spec has a user-facing surface (pages, forms, dashboards, components, modals, mobile screens, emails, CLI output). Render a clickable mockup of the actual thing.
  • Concept mode — the spec describes a backend service, data pipeline, algorithm, library, or infra change with no direct visual surface. Render an interactive concept visualization: API explorer, data-flow diagram, state machine, request/response playground, schema explorer.

Mixed specs (UI surface + backend pipeline) get both, composed in one HTML — usually tabs or a primary view with a secondary panel.

If the spec genuinely has no visual surface and nothing interesting to visualize (rare), say so honestly — don't force a misleading visual.

3. Read the matching pattern reference

Before writing the HTML:

  • UI mode → read references/ui-mockup-patterns.md
  • Concept mode → read references/concept-viz-patterns.md

Both modes share the same base template — read assets/base-template.html for the shell, the four-view toggle, annotation system, comment infrastructure, and submit flow. Extend it. Don't reinvent it.

4. Mark elements as commentable

In the live view, every meaningful element gets data-commentable and data-label:

<div class="card" data-commentable data-label="Onboarding pill (collapsed state)">
  <!-- ... -->
</div>

<section data-commentable data-label="Step list — 5 steps">
  <!-- ... -->
</section>

The label is what the developer sees in the comments sidebar and what gets included in feedback.json — make it descriptive enough that "Onboarding pill (collapsed state)" can stand alone in a comment without surrounding context.

Be generous. Mark sections, components, individual controls, key data points, state variants. A typical mockup has 15-40 commentable elements. Under-marking is worse than over-marking — if the dev wants to comment on something and there's no anchor, they're stuck.

Things to mark:

  • Every section header / grouped area
  • Every interactive control (button, input, link)
  • Every data display (table, card, widget) plus important rows/cells
  • Every state variant (the empty state, the error state)
  • Page-level chrome where it matters (nav, header)

Things to skip:

  • Decorative divs that aren't semantically meaningful
  • Background containers
  • Layout-only wrappers

5. Write the HTML

Save to <spec-path>.html — same directory, same basename, .html extension. So docs/superpowers/specs/2026-05-21-onboarding-design.md becomes docs/superpowers/specs/2026-05-21-onboarding-design.html.

Set data-spec-path and data-spec-title on the <body> element — the comment payload includes these so Claude knows what spec the feedback refers to. data-spec-path MUST be the real on-disk path the consume-feedback phase will use to find the source markdown — never a notional path like docs/superpowers/specs/... if the file actually lives elsewhere.

The HTML must be self-contained and openable from file:// (with internet for the CDN scripts on first paint — Tailwind, marked.js, DOMPurify). Vanilla JS for everything else. One file, period.

Embedding the spec markdown — JSON-encode it. The spec markdown lives inside <script type="application/json" id="spec-content">...</script> as a single JSON string:

<script type="application/json" id="spec-content">
"# Your spec title\n\n## Background\n\nThe spec content with any `<\/script>` inside\nstays safe because the leading `<\/` is escaped at emit time."
</script>

Important: even inside a JSON string, the literal byte sequence </script> will be tokenized by the HTML parser and close the surrounding <script> tag. JSON-encoding the content doesn't help here — you must additionally escape any </ sequence as <\/ before emitting. The example above shows the escaped form. The runtime parses it back via JSON.parse(textContent) and the \/ is interpreted as a normal / in the resulting string.

The runtime does JSON.parse(textContent) to recover the original markdown string. This protects against the otherwise-fatal case of a </script> substring in the spec body (web-tech specs love these in code samples) terminating the script tag at parse time and breaking the Spec view.

6. Validate it works

Sanity-check by reading the file:

  • Does it match the spec's intent? Are all key surfaces represented?
  • Does the four-view toggle (Live / Annotated / Comment / Spec) work?
  • Are data-commentable elements generous enough?
  • Are there mock values or behaviors the spec doesn't commit to? Flag those in Annotated view rather than letting them ossify silently.
  • Is the spec markdown fully embedded in the #spec-content block, as a valid JSON string?
  • Is data-spec-path the real path of the source spec (not a notional one)?

7. Tell the user

Report: where the HTML was saved, which mode you picked and why, what to click first, and any decisions you made beyond the spec. Also tell them how to give feedback:

"Open the HTML, click through Live to explore. Switch to Comment mode (top-right) and hover any element to add inline comments. Hit Submit when you're done — it'll give you a copy-to-clipboard or download as feedback.json. Paste or drop the result back here and I'll apply your feedback to the spec and the mockup."

The Four-View Pattern

Every generated HTML has a toggle in the top-right:

  • Live (default) — the working thing, with realistic content. What a stakeholder validates.
  • Annotated — overlay of numbered bubbles linking each load-bearing element back to a section of the spec. What a reviewer audits.
  • Comment — the developer's review surface. Hovering any data-commentable element shows a + button; click to add an inline comment. There's also a General notes textarea at the top of the comments sidebar for feedback that doesn't anchor to a specific element ("overall this feels rushed", "missing the bulk-action flow entirely", "what about i18n"). Submit bundles everything for the Claude round-trip.
  • Spec — the original markdown rendered inline. Self-contained.

The Live + Annotated pair makes the HTML traceable. The Comment view makes it iterative. The Spec view makes it self-contained. All in one file.

Two kinds of feedback

The Comment view captures two distinct kinds of input:

  • Anchored comments — attached to a specific element via data-commentable. Best for: "this button should be bigger", "this column is missing", "this state needs an empty variant".
  • General notes — a free-form textarea in the sidebar, not tied to any element. Best for: cross-cutting concerns, missing-from-the-mockup observations, structural critiques, scope questions.

Both ship in the same feedback.json and both should be addressed in the consume-feedback phase. Don't treat general notes as second-class — they often surface the structural problems anchored comments can't.

Consume-Feedback Phase

When the user returns with feedback (pasted JSON or a dropped *-feedback.json file), the feedback payload looks like:

{
  "feedback_session": {
    "spec_path": "docs/superpowers/specs/2026-05-21-onboarding-design.md",
    "spec_title": "Onboarding Checklist Design",
    "html_path": "/.../2026-05-21-onboarding-design.html",
    "submitted_at": "2026-05-21T14:32:00Z",
    "general_notes": "Overall the flow feels right, but we never cover the multi-workspace case anywhere.",
    "comment_count": 7,
    "comments": [
      {
        "anchor_label": "Onboarding pill (collapsed)",
        "anchor_selector": "[data-commentable]:label=Onboarding%20pill%20(collapsed)::idx=0",
        "text": "Pill should be 56px not 40px — hard to tap on mobile.",
        "created_at": "...",
        "updated_at": "..."
      }
    ]
  }
}

general_notes is omitted from the payload when empty. When present, classify it the same way as anchored comments (spec change / mockup fix / open question / out of scope) — but because it isn't anchored, the change usually touches multiple sections or a top-level concern. Address it explicitly in your report.

Process

  1. Read both the spec markdown and the HTML. Anchor labels in the feedback refer to elements in the HTML; the spec is the source of truth.

  2. Classify each comment. Every comment falls into one of:

    • Spec change — the comment changes what the product should do. Update the spec markdown.
    • Mockup fix — the spec is right; the mockup mis-rendered it. Update only the HTML.
    • Both — spec change that also requires re-rendering. Update both.
    • Open question — the comment surfaces an ambiguity the spec doesn't resolve. Add to the spec's "Open Questions" section and acknowledge in your report.
    • Out of scope / clarification only — the comment doesn't require a code change (e.g., "good", "yes", "consider for v2"). Note it in the report; no edit needed.
  3. Apply changes in this order:

    • First: spec markdown edits, grouped by spec section. Make the diff small and targeted; don't rewrite unrelated paragraphs.
    • Second: HTML edits. If many spec changes affect rendering, it's often cleaner to regenerate the relevant sections of the HTML rather than patching them in place. Use judgment.
  4. Re-validate. Same checks as in the generate phase — four views still work, spec markdown re-embedded, commentable elements still marked.

  5. Report back. For each comment, one line: classification, what changed (file + section), and any open questions raised. Group by spec change vs mockup fix so the user can see the shape of the round-trip.

Don't lose previous comments

The HTML stores comments in localStorage keyed by spec path. After regeneration, the developer's previous comments may still appear (if anchor selectors line up). This is intended — recurring concerns shouldn't disappear silently. If the dev wants a fresh slate, they can clear it from the comments sidebar.

Consuming via the optional server (the "submitted" trigger)

If the developer is using the optional dev server (scripts/serve.sh, see § Optional Server below), they can push feedback directly from the browser by clicking "Send to Claude Code". The server saves the payload to ~/.claude/interactive-spec-feedback/<spec-slug>-<timestamp>.json and instructs the user to type "submitted" in Claude Code.

When the user's message is a short trigger phrase ("submitted", "feedback ready", "feedback sent", "applied", "got it"), do this:

  1. List the feedback directory:
    ls -t ~/.claude/interactive-spec-feedback/*.json 2>/dev/null
    
  2. Pick the most recent file (the first entry). If the directory is empty, there may be a small race between the user clicking "Send" and typing "submitted" — the file may still be writing. Poll once after ~1s:
    sleep 1 && ls -t ~/.claude/interactive-spec-feedback/*.json 2>/dev/null
    
    If still empty after the poll, tell the user nothing was found and ask whether they meant something else (and remind them that serve.sh must be running for the Send button to write the file).
  3. Read it and treat its feedback_session payload identically to a pasted feedback bundle. Run the full consume-feedback phase.
  4. After applying, move the file to ~/.claude/interactive-spec-feedback/processed/ so it isn't re-consumed on the next trigger:
    mv <the-file> ~/.claude/interactive-spec-feedback/processed/
    
  5. Report back with the standard consume-feedback report (classification, what changed, file paths) — plus a note that auto-reload will refresh the open browser tab once the HTML is rewritten.

If the trigger phrase is buried in a longer message ("hey, I just submitted my expense report, can you help with…"), don't auto-consume — the user wasn't asking about the spec. Only treat short, focused messages as triggers.

Core Principles

The HTML is the spec, not a viewer of it. The rendered mockup communicates aesthetic and functional intent in a way prose can't. Claude reads it back as input when implementing. Stakeholders validate it without needing to read markdown.

Be honest about what's decided. Invented detail that looks decisive is the worst failure mode. If the spec says "shows a list of recent items" without specifying sort order, surface that as an open question in Annotated view rather than picking one and pretending it's the spec.

Polished, not pretty for its own sake. Default to polished. Drop to wireframe only when the spec is explicitly early-stage or visual choices are wide open.

Interactive over static. If something can be clicked, hovered, toggled, stepped through, make it so. Interaction is where edge cases surface.

One file. No build step. A .html next to a .md is a first-class artifact. A .html that needs npm install is a hidden runtime.

Mark commentable elements generously. The feedback loop is only as good as the anchor coverage. Under-marking forces the dev to grope for somewhere to attach a thought — they will either give up or attach it to the wrong place.

Re-generatable. The spec is the source of truth. If the spec changes, the HTML gets regenerated. Don't put effort into the HTML that isn't recoverable from the spec.

Anti-Patterns

  • Faking data the spec doesn't commit to.
  • Adding features not in the spec. ("Every dashboard has filters" → no, the spec is the scope.)
  • Lorem ipsum. Use realistic copy, or surface the gap as [TBD copy].
  • Sparse data-commentable coverage. If the dev hovers around and finds nothing they can comment on, the round-trip is broken.
  • Pretending the HTML is the production code. It isn't; it's the spec rendered.
  • Patching the HTML in place when many comments cluster on the same area. Sometimes it's cleaner to regenerate that section. Use judgment.

Self-Review Before Finishing (Generate Phase)

  1. Spec fidelity — every claim in the HTML traces to a sentence in the spec, or is acknowledged in Annotated view.
  2. Comment coverage — every section, component, control, and state variant has data-commentable + a descriptive data-label. Count: at least 15 commentable elements for a typical spec.
  3. Four views work — Live, Annotated, Comment, Spec.
  4. Comment flow works+ button appears in Comment mode, comments save to localStorage, Submit shows the modal, both copy and download produce valid payloads.
  5. No external dependencies beyond Tailwind, marked.js, DOMPurify, and (optionally) Unsplash images.
  6. Spec.md embedded — full markdown in #spec-content, not linked.

Self-Review After Feedback (Consume Phase)

  1. Every comment addressed — either applied as a change or explicitly noted as open-question / out-of-scope.
  2. Spec edits are surgical — no rewrites of paragraphs the feedback didn't touch.
  3. HTML still renders — re-validate the four views.
  4. Report is structured — grouped by classification, file paths cited.

Outputs

Generate phase:

  • A single .html file next to the source spec/plan.
  • A short summary: path, mode, what to click first, decisions beyond the spec, how to submit feedback.

Consume-feedback phase:

  • Updated .md and/or .html files, in place.
  • A structured report grouping each comment by classification with file references.

That's it. The artifact does the work.

Optional Server (livereload + direct submit)

The skill ships an optional local dev server at scripts/serve.sh. Using it is never required — the bare .html artifact works from file:// and round-trips via copy/paste or download. The server adds two pieces of polish:

  1. Auto-reload — when you rewrite the HTML (during consume-feedback), any open browser tab refreshes itself within a second. No Cmd+R.
  2. Direct submit — the HTML's submit modal gains a "Send to Claude Code" button that POSTs the feedback to the server, which writes it to ~/.claude/interactive-spec-feedback/. The user then says "submitted" in Claude Code and the skill picks it up.

How to start it (the user runs this themselves, once per session):

~/.claude/skills/interactive-spec/scripts/serve.sh <spec-directory> [port]
# e.g.,
~/.claude/skills/interactive-spec/scripts/serve.sh docs/superpowers/specs/ 8765

The server prints the URL; the user opens http://localhost:8765/<spec-name>.html instead of file://.... The HTML detects http:// at load time and activates livereload + the Send button automatically. No HTML regeneration needed to opt in — the same generated file behaves richer when served by the dev server.

When recommending this to the user — only suggest it if they're going through several feedback round-trips. For a single review, copy/paste is faster than starting a server. The cost of starting it is one shell command; the benefit is everything subsequent.

Don't auto-start the server — it's the user's choice. Skill behavior is identical whether or not it's running.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.