Skip to content

Preview Portal Audit

The review and delivery portal standardizes the separate HTML files that were previously generated by project-specific scripts.

ExampleSurfaceControlsLightboxDownloadsNotes
guardians-of-the-dawn/review.htmleditor reviewyesyespartialSource for editor approve/regenerate controls and copyable agent handoff.
guardians-of-the-dawn/client-review.htmlclient reviewsimplifiedyespartialSource for client approve/decline/comment mode.
mirchi-mode/preview.htmlfinal previewnonoyesSource for final showcase and download behavior.
dhuaan-music-video/preview.htmlproject previewnononoShould migrate to generated music-video preview.

Standard Surfaces

The portal generates three surfaces per project by default: a tabbed Review (the feedback loop), a clean Preview (the deliverable), and a live Run dashboard (the operations view). Review and Preview are opposite jobs — Review exists to change the output (feedback → regenerate, via the copy→paste-back-to-Claude protocol); Preview exists to show the finished output for upload/delivery; Run exists to watch the render in flight. The former edit / client-review / compare pages are consolidated into Review (a Decide/Compare tab set + an editor↔client mode toggle); they remain valid --surface aliases for back-compat but are no longer generated by default.

FileAudiencePurpose
review.htmloperator ↔ Claude (+ client mode)The single feedback surface. Decide tab: approve/regenerate per unit → VIDEOCLAW_REVIEW_DECISIONS copy. Compare tab: run/version comparison. A low-key client mode toggle swaps controls to approve/decline/comment → VIDEOCLAW_CLIENT_FEEDBACK copy. Absorbs the old edit/client-review/compare surfaces.
preview.htmlfinal viewerPolished, controls-free deliverable: click-to-fullscreen lightbox on every production image, a soundtrack <audio controls preload="none"> player (when a soundtrack is discovered), aspect-aware sizing, and asset downloads. The upload artifact.
run.htmloperatorThe live run dashboard: one card per generation (storyboard scene) with a STATUS badge (done/rendering/pending/failed), the provider job id + error, the input keyframe, a playable in-progress clip (outputs/scene-N.mp4), the exact submit prompt + contract, a spend estimate chip, an event log (events/events.jsonl), per-card copy-command buttons, and a Show › Episode header from show-bible.json. Paints a RED diff-vs-contract alarm when the submitted payload diverged from the current contract (the @tag-hijacks-references bug), backed by the frozen artifacts/run-contract.json snapshot. Auto-refreshes via <meta http-equiv="refresh">, and is regenerated automatically on every produce/execute and execute-status poll (VCLAW_NO_RUN_SURFACE=1 opts out).
projects/index.htmloperatorPortfolio index across generated projects (links to each project's Review + Preview).
projects/clients/<client>/index.htmlclient/operatorClient-filtered index across that client's projects.

Aliases: --surface edit and --surface review both render review.html (editor mode default); --surface client-review renders it with client mode default; --surface compare renders the standalone compare page; --surface run renders the live run dashboard. Default generation is ['review','preview','run'].

Template Registry

The renderer keeps the HTML structure consistent while adapting section labels and ordering for music-video, story-film, documentary, product-ad, sports-recap, and generic-video. Projects can set template or previewTemplate in project.json; unknown values fall back to generic-video.

The portal also reads artifacts/asset-manifest.json for image assets used by generation routes. Local project-scoped image inputs are rendered in a dedicated generation-input section; for Seedance-backed assets this appears as Seedance Input Frames in the music-video template. This makes the exact start-frame/upscaled image being sent into Seedance visible beside the resulting clip, instead of relying only on the generic images/ folder.

When artifacts/filmmaking-prompts.json exists, the portal exposes it under the prompt-packet section, labelled Seedance Prompt Packets for music-video projects. That gives reviewers one place to inspect the generated @image reference map, character-sheet prompts, 9-panel storyboard-grid prompt, and Seedance packet text before or after video generation.

Per-Scene Submit Contract

Each storyboard scene card renders the exact contract that will be submitted for that scene, expanded inline (no click-to-reveal), so an operator can confirm "exactly what you're going to get" before any render spend:

  • Submit prompt — what the model receives. The resolved provider submit text is the seedancePackets[].promptText (the 10-block master prompt) from artifacts/filmmaking-prompts.json, matched to the scene by sceneIndex. The lighter storyboard scenePrompt fields (imagePrompt, animationPrompt, styleFooter) are shown alongside it. This is the convergence point where the multi-shot plan, the cinematography registers, and the story-bible continuity all land in one packet.
  • References — identity lock. Each seedancePackets[].references slot is rendered with its role, a ready/pending badge, and the binding. For character-sheet slots the binding is the Asset:// URI resolved from artifacts/seedance-assets.json by character name (preferring intlAssetUri); an unregistered character renders as <name> · unregistered. Discovered character reference thumbnails are shown beneath the slots. This lets a reviewer confirm which avatar locks which scene, and that every required reference is ready, before submitting.

The data is sourced entirely from on-disk artifacts (storyboard.json, filmmaking-prompts.json, seedance-assets.json); the card falls back gracefully (omitting the missing block) when an artifact is absent.

Soundtrack Player

The preview showcase discovers a project soundtrack and, when one exists, renders a <audio controls preload="none"> player in the header strip. Discovery prefers an explicit soundtrack or audio field in project.json that resolves to an existing project-local audio file, then falls back to the first discovered audio asset (.mp3/.m4a/.wav/.aac). When no soundtrack is found, no <audio> element is emitted (no broken/empty player). The player is preview-only; the editor/review/client-review decision surfaces are unchanged.

Every production image rendered by the showcase carries data-lightbox-group (and data-lb-caption where a caption exists) so the shared initLightbox makes each image click-to-fullscreen with caption and Escape-to-close, with no per-project hand-wiring.

Empty-preview guardrail

When a project has no renderable media, generatePreviewPortalSurfaces returns a non-empty warnings array (echoed to stderr by the vclaw video portal handler) instead of a silently empty page. The usual cause is that the finished cut was staged at the workspace root rather than under projects/<slug>/final/{videos,images,audio} — the only location the portal scans. The pure, exported previewPortalMediaWarnings() computes the list; warnings is always present (empty when media exists) and the stdout JSON stays machine-readable.

Publish Contract

vclaw video publish-preview builds a deterministic R2 upload plan from the HTML file and its local src/href references. vclaw video publish-portal-index uploads a client or global index whose links point into the published run folders.

bash
vclaw video publish-preview \
  --project <slug> \
  --client <name> \
  --bucket <bucket> \
  [--run <id>] \
  [--surface edit|review|client-review|preview|compare|index] \
  [--public-base-url <url>] \
  [--wrangler-bin <path>] \
  [--dry-run]

--project, --client, and --bucket are all required — the handler throws if any is missing. --surface defaults to preview. The client, project, and run path segments are slugified before forming the R2 key, so the upload prefix is clients/<slugified-client>/<slugified-project>/runs/<slugified-run>/.

Each plan item includes:

  • local file path
  • remote R2 key under clients/<client>/<project>/runs/<run>/
  • content type
  • SHA-256 hash
  • public URL when --public-base-url is provided

Use --dry-run first to inspect the plan. Running without --dry-run executes wrangler r2 object put for each item and appends a surface.published event to project-audit.jsonl. Use --wrangler-bin <path> to pin a specific Wrangler executable in CI or agent automation.

Published project pages live under clients/<client>/<project>/runs/<run>/. Published client indexes live at clients/<client>/index.html and link to those project/run pages.

Built to be driven by agent hosts like Claude Code, Claude Desktop, or Codex · Source-available, commercial use requires a paid license.