Skip to content
Conduit

instructions

compositions

Defining compositions, stills, folders, default props and dynamic metadata

Set up

Skills are installed by placing their folder where your agent loads skills.

Part of the collection vercel-labs/json-render.

Copy the text of compositions.md into the instructions file your agent reads (CLAUDE.md, AGENTS.md, .cursor/rules, …). Written for AI coding agents in general (from where the project keeps it; we have not run it).

README

synced Oct 14, 2026

A <Composition> defines the component, width, height, fps and duration of a renderable video.

It normally is placed in the src/Root.tsx file.

import {Composition} from 'remotion';
import {MyComposition} from './MyComposition';

export const RemotionRoot = () => {
  return <Composition id="MyComposition" component={MyComposition} durationInFrames={100} fps={30} width={1080} height={1080} />;
};

Default Props

Pass defaultProps to provide initial values for your component.
Values must be JSON-serializable (Date, Map, Set, and staticFile() are supported).

import {Composition} from 'remotion';
import {MyComposition, MyCompositionProps} from './MyComposition';

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyComposition"
      component={MyComposition}
      durationInFrames={100}
      fps={30}
      width={1080}
      height={1080}
      defaultProps={
        {
          title: 'Hello World',
          color: '#ff0000',
        } satisfies MyCompositionProps
      }
    />
  );
};

Use type declarations for props rather than interface to ensure defaultProps type safety.

Folders

Use <Folder> to organize compositions in the sidebar.
Folder names can only contain letters, numbers, and hyphens.

import {Composition, Folder} from 'remotion';

export const RemotionRoot = () => {
  return (
    <>
      <Folder name="Marketing">
        <Composition id="Promo" /* ... */ />
        <Composition id="Ad" /* ... */ />
      </Folder>
      <Folder name="Social">
        <Folder name="Instagram">
          <Composition id="Story" /* ... */ />
          <Composition id="Reel" /* ... */ />
        </Folder>
      </Folder>
    </>
  );
};

Stills

Use <Still> for single-frame images. It does not require durationInFrames or fps.

import {Still} from 'remotion';
import {Thumbnail} from './Thumbnail';

export const RemotionRoot = () => {
  return <Still id="Thumbnail" component={Thumbnail} width={1280} height={720} />;
};

Calculate Metadata

Use calculateMetadata to make dimensions, duration, or props dynamic based on data.

import {Composition, CalculateMetadataFunction} from 'remotion';
import {MyComposition, MyCompositionProps} from './MyComposition';

const calculateMetadata: CalculateMetadataFunction<MyCompositionProps> = async ({props, abortSignal}) => {
  const data = await fetch(`https://api.example.com/video/${props.videoId}`, {
    signal: abortSignal,
  }).then((res) => res.json());

  return {
    durationInFrames: Math.ceil(data.duration * 30),
    props: {
      ...props,
      videoUrl: data.url,
    },
  };
};

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyComposition"
      component={MyComposition}
      durationInFrames={100} // Placeholder, will be overridden
      fps={30}
      width={1080}
      height={1080}
      defaultProps={{videoId: 'abc123'}}
      calculateMetadata={calculateMetadata}
    />
  );
};

The function can return props, durationInFrames, width, height, fps, and codec-related defaults. It runs once before rendering begins.

Nesting compositions within another

To add a composition within another composition, you can use the <Sequence> component with a width and height prop to specify the size of the composition.

<AbsoluteFill>
  <Sequence width={COMPOSITION_WIDTH} height={COMPOSITION_HEIGHT}>
    <CompositionComponent />
  </Sequence>
</AbsoluteFill>
↑↓ navigate openesc close