Skip to content
Content
Skill

/storyboard-html-preview

Render a structured storyboard (storyboard.md, shots.json, text-overlays.json, brand-lock.snapshot.md) into a single-file HTML preview that is shareable, printable, and offline. Use when the user wants to share a storyboard, export for review, hand off to an editor, or print a

From plugin
shotkit
205 skills
Install
$ npx -y skills add whystrohm/shotkit --skill storyboard-html-preview --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/storyboard-html-preview

Context preview

The summary Claude sees to decide when to auto-load this skill.

Render a structured storyboard (storyboard.md, shots.json, text-overlays.json, brand-lock.snapshot.md) into a single-file HTML preview that is shareable, printable, and offline. Use when the user wants to share a storyboard, export for review, hand off to an editor, or print a

SKILL.md

storyboard-html-preview.SKILL.md
name: storyboard-html-preview
description: Render a structured storyboard (storyboard.md, shots.json, text-overlays.json, brand-lock.snapshot.md) into a single-file HTML preview that is shareable, printable, and offline. Use when the user wants to share a storyboard, export for review, hand off to an editor, or print a hard copy. Triggers on "preview the storyboard", "share this", "export to HTML", "print version", or after a storyboard-architect run. Produces one self-contained .html file with no build or server.

Storyboard HTML Preview

You are turning structured storyboard files into a single shareable HTML document. The output is what an editor, stakeholder, or client opens in a browser without thinking about it.

The constraint is non-negotiable: **single file, no build step, no server, works offline.** Any time the output requires "run this build command" or "host this somewhere," the skill has failed.

When to use

Trigger when the user:

  • Asks to preview, share, or export a storyboard
  • Wants a printable version
  • Says "what's the next step" after a storyboard-architect run
  • Hands off `storyboard.md` + `shots.json` + asks for a deliverable for review

What you produce

One file: `preview.html`. Self-contained. Inline CSS. No JavaScript dependencies (vanilla JS only, embedded). No external font files (uses system stack with brand-font fallbacks). No external images (placeholder slots; if generated images exist, embed as base64 OR reference relative paths).

output/
├── run.json                   # input, for the run id and date
├── storyboard.md              # input
├── shots.json                 # input
├── text-overlays.json         # input
├── brand-lock.snapshot.md     # input
├── frames/round-N/            # input, if generation has happened
├── critiques/round-N/         # input, for the verdict badges
└── preview.html               # ← what this skill produces

If the user has generated frames, the HTML references them via relative paths so the file works when the whole `output/` folder is shared. Resolve a shot's frame in this order:

1. An entry in `shot.assets.generated` marked `accepted: true` 2. The newest entry in `shot.assets.generated` 3. `frames/round-{highest}/{shot_id}.{png,jpg,jpeg,webp}` 4. `generated/{shot_id}.{ext}`, the pre-3.0.0 flat layout

Data first, convention second. Reading the path convention first meant the page showed whatever file happened to sit there, accepted or rejected, first draft or fifth re-roll.

If no frames exist yet, the HTML uses styled placeholder cards with the shot spec, still useful for review and handoff.

Workflow

Step 1. Read inputs

Required:

  • `shots.json`
  • `text-overlays.json`
  • `brand-lock.snapshot.md`

Optional:

  • `run.json` (for the run id and date; without it the page says "not recorded")
  • `storyboard.md` (for narrative context, surface the brief at the top)
  • `frames/round-N/{shot_id}.{png,jpg,jpeg,webp}` (if generation has happened)
  • `critiques/round-N/{shot_id}.critique.json` (for verdict badges)

Validate before rendering, and stop if it fails:

python tools/validate_shots.py output/

Step 2. Extract brand parameters

From `brand-lock.snapshot.md`, extract:

  • Palette (hex values), used for HTML accent colors
  • Display font and body font names, used as font-family values with system fallbacks
  • Brand voice / mood, used in subtle copy choices

The HTML preview should *feel* like the brand without going overboard. Quiet branding, not loud.

Step 3. Generate the HTML

Use `templates/preview.html.tpl` as the structural template. Read it before generating.

The HTML structure:

<!DOCTYPE html>
<html>
<head>
  <meta>
  <title>{project title}</title>
  <style>
    /* All CSS inline. ~200 lines. Brand-aware. */
    /* Print stylesheet included. */
  </style>
</head>
<body>
  <header>
    <!-- Project title, duration, aspect, generated timestamp -->
  </header>

  <section class="brief">
    <!-- Brief summary if storyboard.md provides one -->
  </section>

  <section class="series-lock">
    <!-- Character / environment / lighting / color grade -->
  </section>

  <section class="shots">
    <!-- One card per shot -->
    <article class="shot" id="shot_01">
      <div class="shot-frame">
        <!-- generated image OR styled placeholder -->
      </div>
      <div class="shot-meta">
        <!-- timestamp, framing, angle, motion -->
      </div>
      <div class="shot-subject">
        <!-- subject description -->
      </div>
      <div class="shot-text-overlay">
        <!-- if on_screen_text exists, show overlay content with timing -->
      </div>
      <div class="shot-rationale">
        <!-- rationale text -->
      </div>
    </article>
    <!-- ... -->
  </section>

  <footer>
    <!-- audit trail: brand-lock snapshot reference, timestamp -->
  </footer>

  <script>
    /* Vanilla JS only. Optional: keyboard nav, jump-to-shot, expand/collapse. */
  </script>
</body>
</html>

Step 4. Embed frames if available

Resolve each shot's frame by the order in "What you produce" above, then reference it by a path relative to the output root:

<img src="frames/round-2/shot_01.png" alt="shot_01: hook" loading="lazy" />

This works when the whole output folder is zipped and shared.

For hard-copy print (a single file with no folder structure), the skill can offer to inline frames as base64. Ask the user which they prefer if frames are present.

If a shot's `assets.generated` entry carries a `sha256` and the file no longer matches it, render the frame but say so on the page. That mismatch means the frame changed after it was recorded, which is exactly the case where a preview quietly showing the new file is worse than one that flags it.

If no frames exist, render styled placeholder cards showing the framing, subject, and shot spec. These are still useful for stakeholder review at the storyboard stage.

**Template flag convention.** When composin

Read more
Ships withshotkit

The pre-production system we use to ship hundreds of videos a month. Open-sourced.

Get the whole plugin
Stats
20
Stars
5
Forks
Maintained
Maintenance
Python
Language
Apache-2.0
License
1mo ago
Last commit
4mo ago
Created

Repo: whystrohm/shotkit

Other skills on shotkit.