Skip to content
Esc
navigateopen⌘Jpreview
On this page

Next.js integration

Use one repository for web routes and videos without coupling the two entry systems.

Install Odori in an existing Next.js application:

pnpm add odori @odori/next
pnpm add -D @odori/cli
pnpm odori init
  • app/
    • page.tsx
    • videos/
      • [id]/
        • page.tsx
    • api/
      • exports/
        • route.ts
  • videos/
    • layout.tsx
    • components/
      • title-reveal/
        • title-reveal.tsx
        • title-reveal.preview.tsx
    • launch/
      • video.tsx
  • components/
    • product-ui/
  • odori.config.ts
  • next.config.ts
import {withOdori} from "@odori/next";
import type {NextConfig} from "next";

const nextConfig: NextConfig = {};

export default withOdori(nextConfig);

The integration generates static imports for videos/ and exposes the catalog to server and client code without importing Node-only render machinery into the browser bundle.

Embed a live preview

import {OdoriPlayer} from "@odori/next/player";
import {getVideo} from "@odori/next/server";

export default async function VideoPage({params}) {
  const {id} = await params;
  const {entry} = await getVideo(id);

  return <OdoriPlayer entry={entry} controls autoPlay />;
}

@odori/next/player is a client component. Page chrome, metadata, and the reserved player aspect ratio can remain in the server-rendered shell.

Queue an export

import {createExport} from "@odori/next/server";

export async function POST(request: Request) {
  const input = await request.json();
  const job = await createExport(input);
  return Response.json(job, {status: 202});
}

createExport() freezes the manifest and records a queued job. Read job state with getExport(id) and list history with listExports(). Render workers stay deployment-independent: the application submits jobs and reads status, and does not need Chromium in every application function.

Was this page helpful?