RVE LogoReact Video EditorDOCS
RVE Pro/Integration Guides/React/Using RVE in a Pure React App

Using RVE in a Pure React App

Step-by-step guide to integrate React Video Editor (RVE) into any React app - no Next.js or Vite required.

Overview

This guide shows how to add React Video Editor (RVE) to any React application, regardless of your bundler or toolchain. Whether you're using Create React App, Parcel, esbuild, Rspack, or a custom Webpack setup - RVE works anywhere React runs.

You will:

  • Confirm your bundler can handle CSS imports
  • Set up Tailwind CSS
  • Configure TypeScript path aliases
  • Add RVE dependencies and migrate code

Prerequisites: Node.js 18+, npm or pnpm, a working React 18+ or 19+ app with a module bundler.

No framework lock-in

RVE has zero framework-specific code internally. It doesn't import from next/, doesn't use import.meta.env, and doesn't rely on any Vite or Next.js APIs. Any bundler that can process React + CSS will work.

Nudge for a Video Tutorial

Tired of reading long wordy docs? Same. Email hello@reactvideoeditor.com and tell Sam (our founder) to make some video tutorials.

Quick checklist

  • React 18+ or 19+ app with a module bundler
  • Tailwind CSS configured and imported
  • @ alias points to ./src
  • RVE deps installed and editor component wired
  • Rendering backend endpoint configured

1) Confirm your bundler handles CSS imports

RVE ships a pre-built styles.css. Your bundler needs to handle CSS imports - all modern bundlers do this out of the box:

  • Webpack (CRA, custom): Built-in via css-loader + style-loader
  • Parcel: Built-in, zero config
  • esbuild: Built-in with --bundle
  • Rspack: Built-in

No special plugin is needed.

2) Install Tailwind CSS

If your project doesn't already use Tailwind, install it with PostCSS:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
pnpm add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

In tailwind.config.js, include your source paths:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{ts,tsx,js,jsx}",
  ],
  theme: { extend: {} },
  plugins: [],
};

In your main CSS file (e.g. src/index.css), import Tailwind:

@tailwind base;
@tailwind components;
@tailwind utilities;

3) Configure TypeScript path alias

In your tsconfig.json, add the @ alias:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

You also need to configure your bundler to resolve the same alias. Here are examples for common setups:

CRA supports the @ alias automatically if you set baseUrl in tsconfig.json. If using a CRA fork or CRACO:

// craco.config.js
const path = require("path");

module.exports = {
  webpack: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
};
// webpack.config.js
const path = require("path");

module.exports = {
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
};

Parcel reads tsconfig.json paths automatically - no extra config needed.

// build.js
require("esbuild").build({
  // ...
  alias: {
    "@": "./src",
  },
});

Also install Node types:

npm install -D @types/node
pnpm add -D @types/node
yarn add -D @types/node

4) Initialize shadcn/ui (optional)

npx shadcn@latest init

Choose any color/theme you prefer.

5) Add dependencies

Copy the dependencies from your RVE Pro project's package.json into your app's package.json.

Ensure you use the latest package.json

The dependencies section may look something like this (note that versions and packages may vary) so its important you check the package.json from the RVE Pro repo.

{
  "dependencies": {
    "@radix-ui/react-alert-dialog": "^1.1.2",
    "@remotion/bundler": "4.0.356",
    "@remotion/cli": "4.0.356",
    "@remotion/google-fonts": "4.0.356",
    "@remotion/lambda": "4.0.356",
    "@remotion/player": "4.0.356",
    "@remotion/renderer": "4.0.356",
    "date-fns": "^4.1.0",
    "mediabunny": "^1.11.2",
    "posthog-js": "^1.268.6",
    "react-best-gradient-color-picker": "^3.0.14",
    "react-hotkeys-hook": "^4.6.1",
    "remotion": "4.0.356",
    "tailwindcss-animate": "^1.0.7",
    "uuid": "^10.0.0",
    "zustand": "^4.4.6"
  }
}

Then install:

npm i

6) Copy RVE source

  • From your RVE Pro project, copy the reactvideoeditor directory into your app under src/reactvideoeditor.
  • Copy constants.ts into your app's src directory.

7) Wire up the editor

Create your editor component (e.g. src/Editor.tsx):

import React from "react";

import { HttpRenderer } from "@/reactvideoeditor/pro/utils/http-renderer";
import { ReactVideoEditor } from "@/reactvideoeditor/pro/components/react-video-editor";
import { createPexelsVideoAdaptor } from "@/reactvideoeditor/pro/adaptors/pexels-video-adaptor";
import { createPexelsImageAdaptor } from "@/reactvideoeditor/pro/adaptors/pexels-image-adaptor";
import { DEFAULT_OVERLAYS } from "@/constants";
import "@/reactvideoeditor/pro/styles.css";
import logo from "./assets/logo.png";

export default function Editor() {
  // A project ID represents a unique editing session/workspace and
  // must match the composition ID defined in the Remotion bundle.
  const PROJECT_ID = "TestComponent";

  // Point this to your own rendering backend.
  // This is NOT a Next.js API route - use any HTTP endpoint you control.
  const ssrRenderer = React.useMemo(
    () =>
      new HttpRenderer("/api/render", {
        type: "ssr",
        entryPoint: "/api/render",
      }),
    []
  );

  return (
    <div className="w-full h-full fixed inset-0">
      <ReactVideoEditor
        projectId={PROJECT_ID}
        defaultOverlays={DEFAULT_OVERLAYS as any}
        fps={30}
        renderer={ssrRenderer}
        disabledPanels={[]}
        defaultTheme="dark"
        sidebarLogo={<img src={logo} alt="Logo" className="w-6 h-6" />}
        adaptors={{
          video: [createPexelsVideoAdaptor("your-pexels-api-key")],
          images: [createPexelsImageAdaptor("your-pexels-api-key")],
        }}
        showDefaultThemes
        sidebarWidth="clamp(350px, 25vw, 500px)"
        sidebarIconWidth="57.6px"
        showIconTitles={false}
      />
    </div>
  );
}

Then render it from your app entry point (e.g. src/App.tsx or src/index.tsx):

import Editor from "./Editor";

function App() {
  return <Editor />;
}

export default App;

8) Set up your rendering backend

Unlike Next.js, you don't have a built-in API route. You need an HTTP endpoint that handles rendering requests. The HttpRenderer will POST to whatever URL you provide.

Options:

  • A separate Express/Fastify/Hono server
  • A serverless function (AWS Lambda, Cloudflare Workers, etc.)
  • Any HTTP endpoint that can invoke Remotion's renderer

Example with Express:

import express from "express";

const app = express();
app.use(express.json());

app.post("/api/render", async (req, res) => {
  // TODO: Wire to your Remotion rendering logic
  res.json({ ok: true });
});

app.listen(3001);

Point your HttpRenderer URL to this server (e.g. http://localhost:3001/api/render in development).

9) Environment variables

RVE Pro was originally built on Next.js, which uses process.env.NEXT_PUBLIC_*. In a pure React app, you need to use whatever convention your bundler supports:

BundlerConventionExample
CRA (Webpack)process.env.REACT_APP_*process.env.REACT_APP_PEXELS_API_KEY
Parcelprocess.env.*process.env.PEXELS_API_KEY
Webpack (custom)DefinePluginWhatever you configure
esbuild--defineWhatever you configure

When migrating RVE Pro code, find and replace all occurrences of process.env.NEXT_PUBLIC_ with your bundler's convention.

Place a logo at src/assets/logo.png (or update the import path) and ensure the sidebarLogo prop points to it.

11) Run the app

npm start

The port depends on your setup (CRA defaults to http://localhost:3000).

Notes and troubleshooting

  • No 'use client' needed: Unlike Next.js, you don't need "use client" directives - everything is client-side in a pure React app. The 'use client' strings in RVE's output are harmless and ignored by non-Next.js bundlers.

  • Rendering backend: The HttpRenderer example needs a real backend endpoint. Unlike Next.js where you get API routes for free, you need to set up your own server or serverless function.

  • Path alias issues: If imports using @/ fail, confirm both your tsconfig.json and your bundler's alias config match.

  • Styles not applying: Ensure your main CSS file includes Tailwind directives and that styles.css from RVE is imported in your editor component.

  • ESM vs CJS: RVE ships both formats. If your bundler has trouble with one, check its module resolution settings. Most modern bundlers prefer ESM (.mjs) automatically.