---
title: Layouts and brands
description: Inherit format, typography, motion, safe areas, audio policy, and design tokens through the videos tree.
---

Layouts are modules that establish presentation policy without adding timeline
frames.

```tsx title="videos/layout.tsx" lineNumbers
import {defineBrand, defineVideoLayout} from "odori";

export const odoriBrand = defineBrand({
  name: "odori",
  colors: {
    background: "#000000",
    surface: "#0a0a0a",
    foreground: "#ededed",
    muted: "#a1a1a1",
    accent: "#ffffff",
    border: "#1f1f1f",
  },
  typography: {sans: '"Geist Sans", sans-serif', mono: '"Geist Mono", monospace'},
  fonts: [
    {family: "Geist Sans", url: "/fonts/Geist-Variable.woff2", weight: "100 900"},
    {family: "Geist Mono", url: "/fonts/GeistMono-Variable.woff2", weight: "100 900"},
  ],
  motion: {standard: [0.16, 1, 0.3, 1], staggerFrames: 3},
  audio: {cues: {"bed.main": "score"}, targetLufs: -14},
});

export const productLayout = defineVideoLayout({
  format: {width: 1920, height: 1080, fps: 30},
  brand: odoriBrand,
  safeArea: {x: 96, y: 72},
});
```

`videos/social/layout.tsx` can override the format while inheriting the brand:

```tsx
import {defineVideoLayout} from "odori";
import {productLayout} from "../layout";

export const socialLayout = defineVideoLayout({
  extends: productLayout,
  format: {width: 1080, height: 1920},
  safeArea: {x: 64, y: 120},
});
```

## Merge rules

- scalar format values replace inherited values
- safe areas replace as a unit
- motion and audio policies merge onto the inherited policy
- a brand replaces the inherited brand, because a brand is itself resolved policy

## Fonts are policy, not imports

A brand declares font families and URLs. The runtime injects the matching
`@font-face` rules and the render worker waits for `document.fonts.ready`
before capturing a frame, so a still, a preview, and an export use identical
faces. Serve font files from `public/`.

## Brands are policy, not a template

A brand provides tokens, fonts, motion curves, audio options, and component
defaults. It should guide installed components without forcing every video into
the same scene sequence.

Any module under a `brands/` directory is discovered, so Studio can preview a
video with a different token set without editing component source:

```ts title="videos/brands/paper.ts"
import {defineBrand} from "odori";

export const paperBrand = defineBrand({
  name: "paper",
  colors: {background: "#fafafa", surface: "#ffffff", foreground: "#0a0a0a", border: "#e5e5e5"},
});
```

Components read tokens through `useBrand()`, and the runtime also exposes them
as CSS variables such as `--odori-foreground` for styles that are easier to
express in CSS.
