Studio
The filesystem-driven workspace for discovering, previewing, and stress-testing Odori videos and components.
pnpm odori dev opens one local workspace for complete videos and for the
source-owned components used to build them. Authors do not need a separate
application, a custom preview route, or an encoded MP4 while editing.
Filesystem contract
Studio discovers project resources under videos/. The entry filename
determines how each module is treated.
videos/**/video.tsx → complete exportable videos
videos/**/*.preview.tsx → development-only component previews
videos/**/brands/*.ts → brand token sets
Directory names carry no discovery semantics. videos/components/ is
discoverable through its preview files, while videos/lib/ remains ordinary
source because it contains no entry filename.
import {defineComponentPreview} from "odori/preview";
import {TitleReveal} from "./title-reveal";
export default defineComponentPreview({
title: "Title reveal",
category: "Typography",
component: TitleReveal,
canvas: {width: 1920, height: 1080, duration: "4s"},
controls: {
title: {type: "text", defaultValue: "Ship the story.", maxLength: 64},
align: {type: "select", options: ["left", "center"], defaultValue: "center"},
},
examples: [
{name: "Default", props: {title: "Ship the story."}},
{name: "Two lines", props: {title: "Build videos\nlike applications."}},
],
});
One workspace for the whole project
| View | Purpose |
|---|---|
| Videos | Browse every composition, select inputs, play the timeline, inspect scenes, and export. |
| Components | Browse every *.preview.tsx fixture, vary props, switch examples, and stress-test formats and brands. |
| Brands | Preview any video with any discovered token set, and read the resolved policy. |
| Assets | Inspect declared assets, brand fonts, and every discovered source file. |
Videos and components use the same canvas and the same playback engine. Switching from a full composition to one component does not change the authoring model.
Video preview
A discovered video is immediately playable without encoding an MP4. Studio reads its metadata and schema to provide:
- a searchable library and a gallery of animated thumbnails
- timeline playback, scrubbing, frame stepping, and scene navigation
- generated input controls from
schema.ts - resolved format, brand, duration, and source file
- a safe-area overlay
- diagnostics for duration drift, duplicate scene IDs, and unusably short scenes
- one explicit export action, defaulting to a distributable MP4
Component preview
A discovered component preview provides:
- a gallery grouped by narrative role
- generated prop controls from the preview contract
- named examples and variants
- brand token switching without changing component source
- 16, 9, and 1 canvases for layout stress tests
Chrome and theme
Studio follows your system theme and can be pinned to light or dark from the top bar. The choice persists per browser. A composition never follows it: a video always renders its brand’s own colors, because the video is the product and the workspace is only the frame around it.
The top bar also links to the documentation. Point it wherever your docs live:
export default defineConfig({docsUrl: "https://odori.dev/docs"});
Keyboard
| Key | Action |
|---|---|
space |
Play or pause |
← → |
Step one frame, or one second with shift |
[ ] |
Jump to the previous or next scene boundary |
home end |
Jump to the first or last frame |
s |
Toggle the safe-area overlay |
l |
Toggle looping |
m |
Mute or unmute audio |
g |
Toggle the gallery |
⌘K |
Open the command palette |
⌘1 to ⌘4 |
Switch views |
Selections are routeable as real paths: /videos/launch and
/components/title-reveal open directly, and the browser’s back button works.
The wordmark opens /, an overview of everything the
project contains, where each row opens the view that owns it.
Export from Studio
The export panel posts to the dev server, which runs the same render worker the CLI uses. It is a single action with a menu, so the common case is one click and the alternatives stay one step away:
| Choice | Result |
|---|---|
| MP4 video | Queues a job, reports progress, and writes an MP4 to the export directory |
| PNG frame | Writes the current frame to the export directory |
| Frame to clipboard | Copies the current frame as an image, writing no file to the export directory |
The menu selection becomes the button’s default for the session. Jobs are listed by the file they wrote, with the full path on hover.
Production separation
Preview modules are development-only inputs. They never enter a production
video bundle or change an export. The renderer compiles videos/**/video.tsx
and its imported runtime dependencies. Studio separately loads *.preview.tsx
files to build development controls and fixtures.