Plate
PlateEditorsTemplates
GitHub16kGitHub
DiscordDiscord
  • Feature Kits
  • Plugin
    • Plugin Methods
    • Plugin Shortcuts
    • Plugin Context
    • Plugin Components
    • Plugin Rules
    • Editing Behavior
    • Plugin Input Rules
  • Editor
    • Editor Methods
    • Controlled Value
  • Authored Changes
  • Performance
  • Static Rendering
  • HTML
  • Markdown
  • Form
  • TypeScript
  • Debugging
  • Unit Testing
  • Browser
  • Troubleshooting
  • Locations
  • Transactions
  • Serializing
  • Roots
  • Document Meta
  • Clipboard and Paste
  • Decorations, annotations, and widgets
  • Schema
  • History
  • Pagination
  • Annotations
  • DOM Coverage
  • External Text Views
  • Virtualized Rendering

Serializing

PreviousNext

Save complete Plate documents and convert them to text, HTML, Markdown, or DOCX.

Save the editor's JSON value when you need an editable document. Use a format serializer when you need to exchange content with another application.

Choose a format

TaskAPI or guide
Save the complete editor documenteditor.read.value() and Document Meta
Export plain textNodeApi.string
Render HTML on the serverrenderStaticHtml from and
TransactionsRoots

On This Page

Choose a formatSave the documentPlain textHTMLMarkdown and DOCXInsert decoded content
Build your editor
Production-ready AI template and reusable components.
Get all-access
platejs/static
HTML
Parse or export MarkdownMarkdownPlugin and Markdown
Import or export Word documentsDOCX
Preserve review proposals in an exportAuthored Changes
Control browser copy and pasteClipboard

Save the document

editor.read.value() includes primary children, named roots, and persistent metadata. EditorRoot passes the same complete value to onValueChange.

const document = editor.read.value();
const schema = editor.read.schema.identity();
 
await saveDocument({ document, schema });
const document = editor.read.value();
const schema = editor.read.schema.identity();
 
await saveDocument({ document, schema });

Persist an application-owned schema identity with the document when stored data needs versioned upgrades. Load the envelope through the editor's document migration path before schema fitting. See Document Model.

Saving only children drops named roots and persistent metadata. Store comment bodies, permissions, and audit events in their owning application store; keep document-owned IDs and metadata with the document.

Plain text

import { NodeApi, type Descendant } from 'platejs';
 
const serializePlainText = (nodes: readonly Descendant[]) =>
  nodes.map((node) => NodeApi.string(node)).join('\n');
 
const text = serializePlainText(editor.read.children());
import { NodeApi, type Descendant } from 'platejs';
 
const serializePlainText = (nodes: readonly Descendant[]) =>
  nodes.map((node) => NodeApi.string(node)).join('\n');
 
const text = serializePlainText(editor.read.children());

This output intentionally loses block types, marks, links, named roots, and review metadata.

HTML

Use Static Rendering to bind server-safe components to the editor's plugins, then render HTML through platejs/static. The HTML guide owns complete import and export examples.

The installed plugins define the schema and accepted HTML. Configure the owning plugin's HTML codec for custom tags and attributes. Keep external HTML sanitization, allowed URLs, and application-specific restrictions at the import boundary.

For a custom string serializer, escape both text and attribute values before writing markup. A generic tree walk cannot infer your custom element semantics.

Markdown and DOCX

Install MarkdownPlugin before calling editor.api.markdown.serialize() or deserialize(). Feature codecs define the representation of their nodes and marks; configure those codecs on the plugin that owns the document shape.

DOCX import and export have separate entrypoints: platejs/docx/import and platejs/docx/export. Use their diagnostics to decide how the app handles unsupported source content.

Ordinary format output represents document content. To preserve proposals and author history, choose an explicit authored projection and use the authored format helpers described in Authored Changes.

Insert decoded content

Use a closed fragment when the parser has complete nodes:

editor.update.fragment.replace(children);
editor.update.fragment.replace(children);

Use ContentSlice when the input preserves open structural boundaries:

editor.update.slice.replace(slice);
editor.update.slice.replace(slice);

Slice validation rejects malformed JSON and impossible open depths. Fitting checks the installed vocabulary, properties, roots, and grammar before publishing a replacement. Use editor.read.slice.fitContent for a detached preview that must not change the document.

A clipboard policy can be narrower than a file-import policy. Keep those policies with the corresponding codec or domCommands.insertData contribution rather than changing the saved document format.