App Builder
Build, revise, and publish one workshop booking app. Sample: Forma.
The original Clay House booking flow.
Copy the prompt into your coding agent. Choose a complete product example, then adapt its React surfaces, content, brand, and assets while preserving the shared timeline.
Install manually
pnpm create odori@latest my-video
cd my-video
pnpm install
pnpm dlx @odori/cli@latest add template workshop-builder
node videos/workshop-builder/select-variation.mjs pottery
pnpm dlx @odori/cli@latest devnpm create odori@latest my-video
cd my-video
npm install
npx @odori/cli@latest add template workshop-builder
node videos/workshop-builder/select-variation.mjs pottery
npx @odori/cli@latest devyarn dlx create-odori@latest my-video
cd my-video
yarn install
yarn dlx @odori/cli@latest add template workshop-builder
node videos/workshop-builder/select-variation.mjs pottery
yarn dlx @odori/cli@latest devbun create odori@latest my-video
cd my-video
bun install
bunx @odori/cli@latest add template workshop-builder
node videos/workshop-builder/select-variation.mjs pottery
bunx @odori/cli@latest devRead ADAPTATION.md in the installed template. Edit selected-input.ts for content and use the schema named in the guide for limits.
Code
videos/workshop-builder/video.tsx
import {layout} from "./layout";
import Composition, {metadata as compositionMetadata} from "./composition";
import {selectedInput} from "./selected-input";
import {inputSchema as inputSchema} from "./schema";
/** The same editable input drives the gallery, Studio, and installed video. */
export const metadata = {...compositionMetadata, layout, schema: inputSchema, defaultProps: selectedInput};
export default function Template(props: Record<string, unknown> = {}) {
return <Composition {...inputSchema.parse({...selectedInput, ...props})} />;
}