When Should I Use registerRoot in Remotion? Entry Point Best Practices
Call registerRoot() exactly once in your Remotion entry file to designate which React component serves as the root of your video composition, enabling the CLI and bundler to locate and render your project.
The registerRoot function is the foundational API that connects your React code to Remotion's rendering pipeline. In the remotion-dev/remotion repository, this single call determines which component becomes the entry point for video generation, whether you are rendering via the CLI or bundling programmatically. Understanding when and where to use registerRoot prevents common configuration errors and ensures your compositions are discoverable by the rendering engine.
What registerRoot Does in Remotion
At its core, registerRoot() tells Remotion which React component should be treated as the entry point of the video. When invoked, the function stores the provided component in a module-level variable (Root) inside /packages/core/src/register-root.ts. This stored reference can later be retrieved by internal APIs such as getRoot() or awaited via waitForRoot(), allowing the rendering engine to mount the correct component tree when generating frames.
The implementation enforces strict validation to prevent runtime errors. It checks that the provided argument is a valid, non-null React component and throws immediately if registerRoot() is invoked more than once, producing the error: Error: registerRoot() was called more than once.
When to Use registerRoot in Remotion
Creating a New Remotion Project
When scaffolding a new project via npx create-remotion or using any official template, you must import registerRoot from the remotion package and call it exactly once at the top level of your entry file (typically src/index.ts or src/index.tsx). Pass your root component—usually the one that contains your <Composition> elements—as the sole argument.
Building Component Libraries
If you are developing a reusable component library intended for consumption by Remotion projects, do not call registerRoot() inside the library. The consuming application must register its own root component. Including registerRoot in a library would cause conflicts when the library is imported, as the registration would happen outside the application's control and likely trigger the "called more than once" error.
Testing and Storybook Environments
When running unit tests or using Storybook to render Remotion components outside the standard bundling flow, you can still call registerRoot() within a dedicated test entry file (for example, test/studio.ts). The same single-call rule applies here—invoke it once to establish the component tree for your test environment, allowing waitForRoot() to resolve correctly during test execution.
CLI Rendering and Programmatic Bundling
For command-line rendering using remotion render, pass the file path containing your registerRoot() call as the entry point argument (e.g., remotion render src/index.ts MyVideo out.mp4). When calling bundle() programmatically from @remotion/bundler, provide the same file path as the entryPoint parameter. The bundler explicitly checks that this file contains the string "registerRoot" and throws a descriptive error if the pattern is missing, unless you deliberately set ignoreRegisterRootWarning to true.
Technical Implementation Details
The bundler in /packages/bundler/src/bundle.ts performs a static validation step before processing. It asserts that the entry point file contains the literal string "registerRoot". This check ensures that users do not accidentally point the bundler at utility files or unrelated source code, providing a clear error message if the pattern is missing.
Internally, the function assigns the component to a module-scoped Root variable. This design allows the rendering engine to access the component synchronously via getRoot() or asynchronously via waitForRoot(), which polls until the root is registered. This mechanism is crucial for environments where the entry file might load asynchronously or when integrating with external tooling that needs to detect when the Remotion tree is ready.
Common Pitfalls When Using registerRoot
Calling registerRoot multiple times – Attempting to invoke the function more than once in the same runtime, even in different files, triggers an immediate throw: Error: registerRoot() was called more than once. Ensure your build pipeline does not accidentally concatenate entry points or double-import registration files.
Using an entry file without registerRoot – When running bundle(), pointing to a file that never calls registerRoot() causes the bundler to throw an error explaining that the file does not contain "registerRoot". Always verify that your entryPoint path resolves to the file where you invoke the registration.
Passing a non-component argument – The function validates that the supplied value is truthy and expects a React component. Passing null, undefined, or a non-function value results in a validation error before rendering begins.
Practical Code Examples
Basic usage in a starter template
In a standard Remotion project created with npx create-remotion, the entry file looks like this:
// src/index.ts
import {registerRoot} from 'remotion';
import {MyVideo} from './MyVideo';
registerRoot(MyVideo);
Awaiting root registration with waitForRoot
For custom runtimes or testing environments where you need to react to registration:
import {waitForRoot} from 'remotion';
waitForRoot((Root) => {
// Execute logic once the root component has been registered
console.log('Root component is ready:', Root.name);
});
Programmatic bundling with entry point validation
When using the bundler API directly:
import {bundle} from '@remotion/bundler';
// This path must point to a file containing registerRoot()
await bundle('src/index.ts', {
onProgress: (p) => console.log(`Bundling ${Math.round(p * 100)}%`),
});
Incorrect entry point (will error)
Attempting to bundle a file without the registration call fails:
// src/utils/helpers.ts – contains no registerRoot()
await bundle('src/utils/helpers.ts');
// ❌ Throws: "this file does not contain \"registerRoot\""
Summary
- Single entry point: Call
registerRoot()exactly once to designate your video's root React component. - Location matters: Invoke it in the file passed to
remotion renderorbundle(), typicallysrc/index.ts. - Library exclusion: Never use
registerRoot()inside reusable component libraries; let the consuming application register the root. - Validation: The function enforces single-call semantics and validates the component, while the bundler verifies the entry file contains the registration string.
Frequently Asked Questions
Can I call registerRoot multiple times in different files?
No. The Remotion runtime strictly enforces that registerRoot() is invoked exactly once per process. Attempting to call it again, even in separate modules, triggers the error registerRoot() was called more than once. If you need to dynamically select a root component, conditionally determine which component to pass to a single registerRoot() call rather than invoking the function multiple times.
Do I need registerRoot if I'm only using the Remotion Player or Preview?
Yes. While the Remotion Player component can render compositions directly in a React web app, the standard Remotion workflow—whether using the CLI remotion render, the bundle() API, or the Studio preview—requires an entry file that calls registerRoot(). This registration establishes the component tree that contains your <Composition> definitions, making them discoverable by the rendering engine and bundler.
What happens if I point the bundler to a file without registerRoot?
The bundler in /packages/bundler/src/bundle.ts performs a static check to ensure the entry point file contains the string "registerRoot". If this check fails, the bundler throws a descriptive error stating that the file does not contain "registerRoot" and instructs you to point to the correct entry file. You can bypass this validation by setting ignoreRegisterRootWarning: true in the bundle options, but this is only recommended for advanced use cases where you are handling registration manually.
Should I use registerRoot in a component library I'm publishing to npm?
No. Component libraries should export React components and compositions, but should never call registerRoot(). The consuming Remotion application must register its own root component that imports and uses your library components. Including registerRoot() in a library would cause registration conflicts when the library is imported into a Remotion project, likely triggering the "called more than once" error or shadowing the application's intended root component.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →