# When Should I Use registerRoot in Remotion? Entry Point Best Practices

> Discover when to use registerRoot in Remotion. Learn essential best practices for your entry point to ensure your video compositions render correctly. Optimize your Remotion setup now.

- Repository: [Remotion/remotion](https://github.com/remotion-dev/remotion)
- Tags: best-practices
- Published: 2026-02-16

---

**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`](https://github.com/remotion-dev/remotion/blob/main//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`](https://github.com/remotion-dev/remotion/blob/main/src/index.ts) or [`src/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/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`](https://github.com/remotion-dev/remotion/blob/main/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`](https://github.com/remotion-dev/remotion/blob/main//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:

```typescript
// 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:

```typescript
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:

```typescript
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:

```typescript
// 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 render` or `bundle()`, typically [`src/index.ts`](https://github.com/remotion-dev/remotion/blob/main/src/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`](https://github.com/remotion-dev/remotion/blob/main//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.