Skip to content
Esc
navigateopen⌘Jpreview

Product launch

The full launch story: headline, source proof, and a closing call to action, scored under one bed.

16:9 · every frame here is the frame odori export writes.

The files

A block is a directory, not a bundle. Pick a file to read the source it ships with.

videos/components/code-proof/end-card/stage/title-reveal/launch/
videos/launch/video.tsx
import {Audio, Scene, Video, defineVideoMetadata} from "odori";
import {CodeProof} from "../components/code-proof/code-proof";
import {EndCard} from "../components/end-card/end-card";
import {Stage} from "../components/stage/stage";
import {TitleReveal} from "../components/title-reveal/title-reveal";
import {productLayout} from "../layout";
import {launchInput} from "./schema";

const SOURCE = `export const metadata = defineVideoMetadata({
  id: "launch",
  title: "Product launch",
  duration: "12s",
});

export default function LaunchVideo() {
  return (
    <Video>
      <Scene id="opening" duration="4s">
        <TitleReveal title="Author the story." />
      </Scene>
    </Video>
  );
}`;

export const metadata = defineVideoMetadata({
  id: "launch",
  title: "Odori launch",
  description: "A concise introduction to the odori authoring model.",
  duration: "12s",
  layout: productLayout,
  schema: launchInput,
  tags: ["launch", "framework"],
  thumbnailFrame: 45,
});

export default function LaunchVideo({
  headline,
  callToAction,
}: {
  headline: string;
  callToAction: string;
}) {
  return (
    <Video>
      {/* One bed under the whole cut, ducked so scene sounds stay audible. */}
      <Audio src="bed.main" gain={0.6} fadeIn="1s" fadeOut="1.5s" duckUnder />

      <Scene id="opening" duration="4s" name="Opening">
        <Stage>
          <TitleReveal title={headline} detail="An independent React video framework." />
        </Stage>
      </Scene>
      <Scene id="proof" duration="5s" name="Proof">
        <Stage grid={false}>
          <CodeProof
            code={SOURCE}
            language="tsx"
            title="videos/launch/video.tsx"
            caption="Static metadata for discovery. Ordinary JSX for the timeline."
          />
        </Stage>
      </Scene>
      <Scene id="resolution" duration="3s" name="Resolution">
        <Audio src="ui.confirm" from="0.2s" duration="1s" gain={0.7} />
        <Stage>
          <EndCard
            title={"One definition.\nEvery render path."}
            detail="Preview needs no encode. Export freezes the approved cut."
            callToAction={callToAction}
          />
        </Stage>
      </Scene>
    </Video>
  );
}

Remix it

Scaffold a project, install the components this block uses, then paste the entry into videos/launch/video.tsx. Every file above is yours to edit from that point on.

pnpm create odori@latest my-video
pnpm odori add @odori/stage @odori/title-reveal @odori/code-proof @odori/end-card

Other blocks