Integrating Excalidraw with Remix React

Excalidraw is a famous Client Side whiteboard tool to make you easy sketch with handwriting style, widely adopted by Developers and Designers.


What is Excalidraw

Excalidraw is an app made by Facebook software engineer Christopher Chedeau.

It is well styled and have a co-working feature that makes it stand out. It is available on After drawing your graph, you could download the png or the raw data.

It can now integrate perfectly with React or straightforward with CDN packages, there’s an brief guide with NEXT.JS as well.

I’m integrating Excalidraw into one of my new Note project with REMIX Application, hope you enjoy.

Excalidraw integrated with REMIX
Result as above

Get Excalidraw and Make a Component

npm i @excalidraw/excalidraw

You should name your Excalidraw component with *.client.tsx to make it client only, or the import function including reading document element, that only available in client, will throw an error.

// ExcalidrawComponent.client.tsx

import { Excalidraw } from '@excalidraw/excalidraw';

export const ExcalidrawComponent = () => {
    return (
            <Excalidraw />

Import it in a Route with ClientOnly Util

If you yet install the client-only package from remix-utils, see It is a package developed by REMIX developer sergiodxa.

You could also refer to, where in my opinion best practice for client side in REMIX.

By the way, you should define height of Excalidraw wrapper or you won’t see it!

import { ClientOnly } from "remix-utils/client-only";
import { ExcalidrawComponent } from "~/components/Excalidraw.client";

export default function ExcalidrawSection() {

    return (
                {() => {
                    return (
                        <div style={{ height: "500px" }}>
                            <ExcalidrawComponent />

Last Step Fixing process is not defined

REMIX app is using vite, which does not expose process variant natively.

In the FAQ section in Excalidraw docs show the way to fix this. Easy as adding define in the vite config.

// vite.config.ts

export default defineConfig({
  plugins: [remix(), tsconfigPaths()],
  define: {
    "process.env.IS_PREACT": JSON.stringify("true"),

Tada now you should see it works on your site! Good day!