Use Plate in React Server Components when you need to render read-only editor content or generate HTML on the server. Interactive editors still belong in client components with platejs/react. This guide shows the server-safe static editor path, HTML serialization, and the boundary with Node-only processing.
Do not import platejs/react or another /react subpath from a Server
Component. Use platejs/static, platejs, and base platejs/* subpaths.
Install the copied base editor kit when you want Plate UI static components and the default serializer plugins.
The editor-plugins-static item installs BaseEditorKit, static node components, and
the editor-static UI component used by server rendering.
Create an editor in the Server Component and render it with
<EditorStatic>.
import { createEditor, type Value } from 'platejs';
import { EditorStatic } from 'platejs/static';
import { BaseEditorKit } from '@/components/editor/plugins-static';
const value: Value = [
{
children: [{ text: 'Server-rendered document' }],
type: 'heading', level: 1,
},
{
children: [{ text: 'This content is rendered without editor state.' }],
type: 'paragraph',
},
];
export default function DocumentsPage() {
const editor = createEditor({
plugins: BaseEditorKit,
initialValue: value,
});
return <EditorStatic editor={editor} />;
}import { createEditor, type Value } from 'platejs';
import { EditorStatic } from 'platejs/static';
import { BaseEditorKit } from '@/components/editor/plugins-static';
const value: Value = [
{
children: [{ text: 'Server-rendered document' }],
type: 'heading', level: 1,
},
{
children: [{ text: 'This content is rendered without editor state.' }],
type: 'paragraph',
},
];
export default function DocumentsPage() {
const editor
Use renderStaticHtml when a route needs the server-rendered HTML for a static
Plate view instead of a React tree.
import { createEditor, type Value } from 'platejs';
import { renderStaticHtml } from 'platejs/static';
import { BaseEditorKit } from '@/components/editor/plugins-static';
import { EditorStatic } from '@/components/editor/editor-static';
const value: Value = [
{
children: [{ text: 'Exported document' }],
type: 'heading', level: 1,
},
{
children: [{ text: 'This HTML is generated on the server.' }],
type: 'paragraph',
},
];
export async function GET() {
const editor = createEditor({
plugins: BaseEditorKit,
initialValue: value,
});
const html = await renderStaticHtml(editor, {
component: EditorStatic,
});
return new Response(html.data, {
headers: { 'content-type': 'text/html; charset=utf-8' },
});
}import { createEditor, type Value } from 'platejs';
import { renderStaticHtml } from 'platejs/static';
import { BaseEditorKit } from '@/components/editor/plugins-static';
import { EditorStatic } from '@/components/editor/editor-static';
const value: Value = [
{
children: [{ text: 'Exported document' }],
type: 'heading', level: 1,
},
{
children: [{ text: 'This HTML is generated on the server.' }],
type: 'paragraph',
},
];
export async
If you only need data transforms or Markdown IO, use the Node.js path instead of static React rendering.
That path uses createEditor from platejs and does not need copied UI
components.
| Runtime | Import from | Use for |
|---|---|---|
| Server Component | platejs, platejs/static | Read-only React output with <EditorStatic>. |
| Route handler | platejs, platejs/static | Static React rendering with renderStaticHtml. |
| Node script | platejs, platejs/* | Validation, migration, Markdown IO. |
| Client editor | platejs/react, platejs/*/react | Editable UI, hooks, toolbar interactions. |
createEditor from platejs installs the core DOM capability that static
output uses. The same editor works for rendered output and for scripts that
only read or transform a value.
| Task | Guide |
|---|---|
| Learn the static renderer. | Static Rendering |
| Generate HTML. | HTML |
| Read or write Markdown. | Markdown |
| Transform content without React. | Node.js |
Done. Your Server Component can render Plate content without shipping the interactive editor runtime.