composebeta

Ship product videos like you ship product.

Compose is a JSX framework for marketing-grade product videos. Capture your real app, frame it with branded chrome, and render an MP4 / WebM / poster pack — all from a .compose.tsx file that lives in your repo. It re-renders when your UI ships, and the diff lands in a pull request.

01

Authored in JSX

A video is a component. Compose scenes, timing, and captions in .compose.tsx — versioned with the code it shows.

02

Captures your real app

Frames come from your running product, not a mockup. The same captures Reshot already takes, in motion.

03

Renders in CI

Run the render headless on every build. When the UI changes, the video re-renders and the diff goes to review.

authored as code

A video is a component, not a timeline.

Instead of dragging clips in an editor that drifts out of date the moment you ship, you describe the video declaratively. Scenes, captions, timing, and the captures they show all live in a .compose.tsx file next to the feature it documents.

Declarative scenes — capture, frame, caption, transition
Lives in the repo and reviews in a pull request like any code
Reuses the scenarios and auth your Reshot captures already use
product-tour.compose.tsx
import { Compose, Scene, Capture, Caption } from "@reshot/compose";

export default function ProductTour() {
  return (
    <Compose brand="reshot" ratio="16:9">
      <Scene capture="billing-overview" hold={2.5}>
        <Caption>One key, every embed</Caption>
      </Scene>
      <Scene capture="review-queue" hold={3} />
    </Compose>
  );
}
real captures

Footage of the product, not a recreation.

Compose drives your actual app the way Reshot already does — against localhost, with the auth and data your team trusts. Every frame in the video is the real UI at the commit it was rendered from, so the demo can never show a screen that no longer exists.

Runs your real scenarios in a headless browser
Captures motion — clicks, navigation, state changes
No screen-recording session to redo every release
frame
branded chrome

Framed on brand, every time.

Wrap raw captures in a branded browser frame, add motion, captions, and a soundtrack — all defined once and applied to every scene. Reps and writers can’t drift off-brand, because the frame is part of the framework, not a manual export step.

Brand chrome, colors, and type applied to every scene
Cursor motion, zooms, and transitions built in
One frame definition, reused across every video you ship
render pack

One render, every format you embed.

A single compose render produces a complete pack — an MP4 for the docs, a WebM for the web, and a poster frame for the embed before it plays. Drop them behind one stable Reshot URL and every surface updates when the video does.

MP4, WebM, and poster from a single render
Served from one durable URL, like the rest of Reshot
MP4
tour.mp4
1080p · 4.2 MB
WEBM
tour.webm
1080p · 2.8 MB
PNG
poster.png
1920×1080
in your pipeline

Re-renders on the deploy that changed the UI.

Run npx reshot compose render in CI. When a build changes a screen the video depends on, Compose re-renders the affected scenes and posts the diff to the pull request — so a stale demo is caught in review instead of by a customer.

Headless render on every build, no manual export
Diff lands in the PR — approve before it publishes
Detect changed capturesbilling-overview · deploy #2184
0:04
Re-capture scenesheadless · localhost
0:51
Render packmp4 · webm · poster
1:18
Post diff to PRawaiting review
total2 min 13 sec

Put your product demos in the repo.

Start with one tour. Author it once, render it in CI, and let it re-render itself every time the product moves.