AGENTS.md · git:20260907.985fba0 · 2026-09-07 · sha256 6cffa345f67bb789
AGENTS.md git:20260907.985fba0A
Immutable. This exact content is served forever at /api/v1/blob/6cffa345f67bb789.
# AGENTS.md
Copy this guide into a Remotion project before an agent writes a composition. In this repository, start with [README.md](./README.md) and [docs/ARQUITETURA.md](./docs/ARQUITETURA.md). The `npm run catalog` command mentioned below belongs to the source generator and is intentionally absent here.
`catalog.json` is generated. Never edit it by hand in this repository.
## Six failure modes
These were found by breaking real compositions. Most fail silently.
### 1. `useVideoConfig()` reports the composition, not its container
Components that calculate font size, safe area, or percentage positions read the dimensions of their `<Composition>`, not the element that contains them. `transform: scale()` shrinks the frame but not its layout calculations.
- To show a 1920×1080 scene in a cell, use the `cena: true` `Item` flag so it renders at full size before it is scaled.
- For vertical work, create a real 1080×1920 `<Composition>`.
- `cena: true` is also required for canvas-percentage components such as `SimulatedCursor`.
### 2. `Sequence` renders an `AbsoluteFill`
It leaves normal flow. Several `Sequence` elements inside a `space-between` flex layout collapse into the upper-left corner. Stack them with explicit absolute `top` and `left` positions, as in `src/playground/pecas.tsx`.
### 3. `defaultProps` crosses a JSON boundary
React elements arrive as `{key, ref, props}` and can trigger React error #31. Do not pass JSX through `defaultProps`; build stable page components in the module instead:
```tsx
const COMPONENTES = Object.fromEntries(
PAGINAS.map((p) => [p.id, () => <Pagina {...p} />]),
);
```
### 4. Effect order and type matter
- Generators (`checkerboard`, `rings`, `lightLeak`, `zigzag`) draw new pixels and discard what was below.
- Filters (`thermalVision`, `halftone`, `pixelate`, `duotone`, `zoomBlur`) transform existing pixels.
A filter with no input produces nothing; a generator at the end erases previous work. Configure effects explicitly—many defaults, including `duotone({})`, are not useful.
### 5. `TransitionSeries` is shorter than the sum of its sequences
Its duration is the sum of sequences minus the overlaps. Two 40-frame sequences with a 20-frame transition last 60 frames, not 80. A longer `<Loop>` leaves black frames. Use `cicloTransicao()` from `pages-extra.tsx`; favor short blocks and longer transitions.
### 6. Some media scenes accept only images
`MediaFrame` and `SplitScreen` choose `<Img>` or `<Video>` through `isVideoSource(src)`. `ZoomPanFrame`, `DeviceMockupZoom`, and `CalloutSpotlight` render only `<Img>`; passing video gives an empty frame without an error. Extract a still instead:
```bash
ffmpeg -ss 3.2 -i public/video.mp4 -frames:v 1 -q:v 2 public/video.jpg
```
Square media in a 16:9 scene produces letterboxing; use `fit="cover"`.
## Three 3D failure modes
These were isolated while porting the authored three.js `LampadaBrowserFlow` scene. They can look correct in Studio and render black in the MP4.
### 3D-1. `UnrealBloomPass` must be last
Outside the final position it creates a framebuffer-to-texture feedback loop. Headless Chromium can discard the draw and every later pass reads black, with no shader, GL, or console error. The behavior reproduces with `--gl=angle` and `--gl=swangle`. Put bloom last; do not use it if later passes are required.
### 3D-2. Final bloom can apply tone mapping and sRGB twice
Drawing with `setRenderTarget(null)` makes three apply `toneMapping` and `outputColorSpace`. With a preceding `OutputPass`, conversion happens twice and produces a washed-out image. In this project the wood floor changed from `(123,101,82)` to `(198,187,176)`. Remove `OutputPass` and let the renderer convert once during the final draw.
### 3D-3. `SMAAPass` r168+ is asynchronous
Its constructor dimensions are ignored and lookup textures load through `new Image()`. A browser animation loop hides this; a one-frame render does not. Use MSAA on the composer target instead: `new WebGLRenderTarget(w, h, { samples: 4 })`.
For all 3D scenes, each frame must be a pure function of `useCurrentFrame()`. React Three Fiber `useFrame()` is clock-driven and non-deterministic in rendered output. Use `useDelayRender()` for async GLB, textures, and shaders. Render the same frame twice in separate processes and compare hashes.
## Environment rules
- Keep `typescript` on `5.x`; the Remotion bundler depends on `ts.sys`.
- Configure the `@/` alias in both `tsconfig.json` and `remotion.config.ts`.
- Restart Studio after changing either configuration file.
- `maplibre-gl` requires WebGL2 and does not render headlessly; `PAGINA_MAPAS` remains deliberately unregistered.
## RemotionUI CLI
- `remotion-ui add` for a composition edits `Root.tsx`; inspect it afterwards.
- `remotion-ui init` creates a nested project when it cannot find config; write `remotion-ui.json` yourself.
- Updating the library can overwrite copied files. Version 0.7.0 rewrote `transition-timing.ts` and changed `TerminalSimulator`; reinstall affected components deliberately.
## Writing a component here
1. Consult `catalog.json` for intent (`quando`) and the import path (`importa`).
2. Import colors and typography from `src/shared/theme.ts` (`PALETTE`, `MONO`, `RADIUS`); do not scatter hex values.
3. Pass explicit `fontSize` when supported.
4. Animate one thing at a time; see `src/recipes/recipes.tsx`.
5. Verify by rendering: `npx remotion still <Id> out/x.png --frame=N`.
6. Run the source generator's `npm run catalog` after adding a page component.
## Attribution and catalog conventions
- Keep identifiers stable. The public interface is English-first with a pt-BR option; generated catalog values remain source data.
- `AUTORAL` applies only to code written here. Never mark library code as authored, and do not infer provenance from memory: `catalog.json.lib` is authoritative.
- The catalog grid is four items per page. Add a page rather than a fifth item.
- Brazil vertical components (`src/remotion/brasil/`) receive `escala`, never `useVideoConfig()`-derived `fontSize`.
## Relationship to official Remotion Agent Skills
The official skills published on 2026-08-14 (commit `9f0faa5`) explain framework use. They complement this repository: Agent Skills explain **how** to write Remotion; `catalog.json` explains **what** is available; this guide explains **where it fails**. The official skills cover `TransitionSeries`; they partially cover composition dimensions, `Sequence`, and JSON-serializable props. Effect ordering and media-scene limitations remain project-specific.
## Repository environment
Comments explain code, never conversations. Do not put home paths or personal email addresses in source. The source generator is not present here. Treat `catalog.json` as read-only except for the optional `preview` field maintained by `scripts/link-previews.mjs`.
- `npm install` installs Remotion 4.0.x, MCP, and AJV.
- `npm run validate` and `npm test` verify the catalog and tooling.
- `npm run studio` serves 102 square compositions at `http://localhost:3000`.
- `npm run web` serves the static viewer at `http://localhost:8080/web/`.
- `npx remotion-catalog find "<intent>"` and `npm run mcp` expose the catalog to tools.
There is no lint command. Run `npm run validate`, `npm test`, and `npm run typecheck` after TypeScript changes. Intentional data nuances include the two distinct Typewriter entries, the multi-listed `AnimatedBarChart`, composed tracks such as `UI + SimulatedCursor`, and four reel recipe stubs without `trilhas`.