Skip to main content

Overview

Integrating Excalidraw with Next.js requires special handling due to server-side rendering (SSR). This guide covers both the App Router and Pages Router approaches, with solutions for SSR compatibility.

Why Dynamic Import?

Excalidraw uses browser-specific APIs that aren’t available during SSR. To prevent errors, we need to:
  1. Disable SSR for the Excalidraw component
  2. Use dynamic imports with ssr: false
  3. Handle client-side only rendering

Installation

1

Install dependencies

2

Configure Next.js

Update your next.config.js to handle TypeScript if needed:
next.config.js
3

Self-host fonts (optional)

Copy fonts to your public directory:
Add this to your package.json scripts:

App Router Integration (Next.js 13+)

The App Router uses React Server Components by default, requiring a client-only wrapper.

Step 1: Create a Wrapper Component

Create src/excalidrawWrapper.tsx:
src/excalidrawWrapper.tsx

Step 2: Dynamic Import in Page

Create your page with dynamic import:
src/app/page.tsx

Step 3: Create Layout

src/app/layout.tsx

Add Global Styles

Create src/app/globals.css:
src/app/globals.css

Pages Router Integration

For the traditional Pages Router, use a similar approach:

Step 1: Create Wrapper Component

src/excalidrawWrapper.tsx

Step 2: Create Page with Dynamic Import

src/pages/index.tsx

Advanced Integration with Custom Features

Create a full-featured integration with custom UI and functionality:

Loading State

Add a loading indicator while Excalidraw loads:

TypeScript Configuration

Ensure your tsconfig.json is properly configured:
tsconfig.json

Polyfills for Server-Side

If you encounter canvas-related errors during build, add polyfills:
Then in your wrapper:

Deployment

1

Build your application

2

Test production build locally

3

Deploy to Vercel

The easiest way to deploy is using Vercel:

Common Issues

This occurs when SSR tries to access browser APIs. Make sure:
  • You’re using dynamic import with ssr: false
  • The "use client" directive is at the top of your wrapper
  • Asset path is set using next/script with beforeInteractive strategy
Ensure:
  • Fonts are copied to the public directory
  • EXCALIDRAW_ASSET_PATH is set correctly
  • Your build script includes the copy:assets step
If you see TypeScript errors related to JSX:
  • Check your tsconfig.json has "jsx": "preserve"
  • Ensure all imports are correctly typed
  • Consider adding // @ts-expect-error for known Next.js issues
Install and import the path2d-polyfill:
Then import it in your wrapper component.

Live Example

View the complete working example:

Next Steps

React Integration

Learn about general React integration patterns

API Reference

Explore the complete API documentation

Vanilla JS

See how to use Excalidraw without a framework

Examples

Browse more integration examples