← Files RemotionARCHIVED FILE
skills/remotion-markup/connected-compositions.md
4.82 KB · Oct 10, 2026 · 06:13 UTC
# Connected compositions
Using the connected compositions pattern, a group of layers can get their own Studio timeline, like a precomposition in After Effects.
Use connected composition when a section has its own layers or timing, will be reused, or would be easier to edit and preview on its own.
1. Put the scene's markup in a named React component.
Multiple internal layers and sequences can live inside it.
2. Prefer making the component interactive with `Interactive.withSchema({wrapInSequence: true})`, following Remotion Interactivity.
Render the exported component directly in the parent with inline timing and editable props.
It does not need an additional `<Sequence>` to connect to its registration.
For consecutive scenes or transitions, render one direct instance as the only child of a `<Series.Sequence>` or `<TransitionSeries.Sequence>`.
3. Register the **same component reference** with `<Composition component={...}>` in the root.
Give it a unique `id` and the dimensions, fps, and natural duration needed to preview the scene on its own. A `<Folder>` can keep scene compositions together.
## Make the component independent of its parent
The parent is not mounted when a connected composition opens on its own.
Define required styles such as `fontFamily` inside the component, and avoid
parent-only context providers or mount side effects. Load custom fonts in its
module or a shared module it imports; see [Google fonts](google-fonts.md) and
[local fonts](local-fonts.md).
When extracting markup, carry over these dependencies. Verify its appearance
by opening it directly in a fresh Studio preview before opening the parent.
## Example
```tsx
// Chapter.tsx
import type React from 'react';
import {
AbsoluteFill,
Interactive,
interpolate,
useCurrentFrame,
type InteractivitySchema,
} from 'remotion';
type ChapterProps = {
readonly title: string;
readonly style?: React.CSSProperties;
};
const ChapterInner: React.FC<ChapterProps> = ({title, style}) => {
// Frame 0 is the start of this chapter, wherever the parent places it.
const frame = useCurrentFrame();
return (
<AbsoluteFill
style={{
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
color: 'black',
fontFamily: 'Helvetica, Arial, sans-serif',
...style,
}}
>
<h1
style={{
fontSize: 96,
opacity: interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: 'clamp',
}),
}}
>
{title}
</h1>
</AbsoluteFill>
);
};
const chapterSchema = {
title: {type: 'text-content', default: '', description: 'Title'},
} as const satisfies InteractivitySchema;
export const Chapter = Interactive.withSchema({
Component: ChapterInner,
componentName: '<Chapter>',
schema: chapterSchema,
wrapInSequence: true,
});
```
`ChapterInner` only declares `title` and `style`.
Because of `wrapInSequence: true`, the exported `Chapter` additionally accepts the timing props of a `<Sequence>`: `from`, `durationInFrames`, `trimBefore`, `playbackRate`, `loop`, `freeze`, `hidden`, `name` and `showInTimeline`, plus `premountFor`, `postmountFor` and crop props.
These are handled by the wrapper and are not passed to `ChapterInner`.
See Prefer interactive components with their own timelines.
```tsx
// MyVideo.tsx
import {Chapter} from './Chapter';
export const MyVideo = () => (
<>
<Chapter name="Opening" durationInFrames={90} title="Introduction" />
<Chapter
name="Feature"
from={90}
durationInFrames={120}
title="New features"
/>
</>
);
```
```tsx
// Root.tsx
import {Composition, Folder} from 'remotion';
import {MyVideo} from './MyVideo';
import {Chapter} from './Chapter';
export const RemotionRoot = () => (
<>
<Folder name="MyVideo-Scenes">
<Composition
id="Chapter"
component={Chapter}
width={1920}
height={1080}
fps={30}
durationInFrames={120}
defaultProps={{title: 'Introduction'}}
/>
</Folder>
<Composition
id="MyVideo"
component={MyVideo}
width={1920}
height={1080}
fps={30}
durationInFrames={210}
/>
</>
);
```
Studio replaces the layers with a reference to the connected composition in the timeline.
Double-clicking a timeline item with one connected composition opens it at the corresponding frame.
Editing the shared component changes both views.
Example: If user has `MyVideo` selected, they can see 2 layers in the timeline, and can double-click one to go to the `Chapter` composition.
If the scene takes props, pass the intended values in the parent and use matching `defaultProps` on its standalone registration; registration does not automatically copy the parent's props.
Keep scene and parent fps and dimensions aligned unless their difference is intentional.
SHA-256: c3f02316826713dff2ad59194e58ae80a5bb4c59fb53945d535d34608b18431c