BlockNote DocsGetting StartedGetting StartedWith Next.js

Getting Started With Next.js

BlockNote is a component that should only be rendered client-side (and not on the server). If you're using Next.js, you need to make sure that Next.js does not try to render BlockNote as a server-side component.

Make sure to use BlockNote in a Client Component. You can do this by creating a separate file for your component (make sure this sits outside of your pages or app directory, for example components/Editor.tsx), and starting that with "use client"; directive:

"use client"; // this registers <Editor> as a Client Component
import "@blocknote/core/fonts/inter.css";
import { useCreateBlockNote } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";

// Our <Editor> component we can reuse later
export default function Editor() {
  // Creates a new editor instance.
  const editor = useCreateBlockNote();

  // Renders the editor instance using a React component.
  return <BlockNoteView editor={editor} />;
}

Import as dynamic

In the same directory, create a new file called DynamicEditor.tsx: Here, we will use Dynamic Imports to make sure BlockNote is only imported on the client-side.

You can import the component we just created above using next/dynamic in your page:

"use client";

import dynamic from "next/dynamic";

export const Editor = dynamic(() => import("./Editor"), { ssr: false });

Import in a page / app

Now, you can import the dynamic editor in your page or app:

import { Editor } from "../components/DynamicEditor";


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

Server-side processing (API Routes)

If you want to use @blocknote/server-util in a Next.js API route (Route Handler) — for example, to convert blocks to HTML on the server — you need to add BlockNote packages to serverExternalPackages in your next.config.ts:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  serverExternalPackages: [
    "@blocknote/core",
    "@blocknote/react",
    "@blocknote/server-util",
  ],
};

export default nextConfig;

Then you can use ServerBlockNoteEditor in your API route as usual:

// app/api/convert/route.ts
import { ServerBlockNoteEditor } from "@blocknote/server-util";

export async function POST(req: Request) {
  const { blocks } = await req.json();
  const editor = ServerBlockNoteEditor.create();
  const html = await editor.blocksToFullHTML(blocks);
  return Response.json({ html });
}

If you use a custom schema with createReactBlockSpec, you can share it between your API routes and your client-side editor. Just define the schema in a separate file and import it in both places — the serverExternalPackages config ensures it works in both contexts.

See the server-side processing docs for more details on ServerBlockNoteEditor.

React 19 / Next 15 StrictMode

BlockNote is not yet compatible with React 19 / Next 15 StrictMode. For now, disable StrictMode in your next.config.ts:

...
reactStrictMode: false,
...

This should resolve any issues you might run into when embedding BlockNote in your Next.js React app!