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 @platejs/*/react from a Server Component.
Use platejs/static, platejs, and base @platejs/* entrypoints.
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 a static editor in the Server Component and render it with
<PlateStatic>.
import type { Value } from 'platejs';
import { createStaticEditor, PlateStatic } 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 = createStaticEditor({
plugins: BaseEditorKit,
initialValue: value,
});
return <PlateStatic editor={editor} />;
}import type { Value } from 'platejs';
import { createStaticEditor, PlateStatic } 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 = createStaticEditor
Use renderStaticHtml when a route needs the server-rendered HTML for a static
Plate view instead of a React tree.
import type { Value } from 'platejs';
import { createStaticEditor, 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 = createStaticEditor({
plugins: BaseEditorKit,
initialValue: value,
});
const html = await renderStaticHtml(editor, {
editorComponent: EditorStatic,
});
return new Response(html, {
headers: { 'content-type': 'text/html; charset=utf-8' },
});
}import type { Value } from 'platejs';
import { createStaticEditor, 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
If you only need data transforms or Markdown IO, use the Node.js path instead of static React rendering.
That path uses createBaseEditor from platejs and does not need copied UI
components.
| Runtime | Import from | Use for |
|---|---|---|
| Server Component | platejs/static | Read-only React output with <PlateStatic>. |
| Route handler | 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. |
createStaticEditor includes the static ViewPlugin before your plugins.
Use it for rendered output. Use createBaseEditor when the script only
reads or transforms 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.