How editor content is serialized and how to handle it.
Both editors use Tiptap under the hood, which manages content as a ProseMirror document. You can retrieve the content in multiple formats depending on your storage and rendering needs.
HTML
HTML is the default output format. Use editor.getHTML() to retrieve the content as an HTML string:
const html = editor.getHTML();
The HTML output is standard HTML with inline styles for certain attributes:
When rendering embeds on your own (outside the editor), detect these by their data-type attribute and render the appropriate iframe/widget.
Block editor
The block editor uses standard Tiptap nodes with no custom node types. Its output follows the same table above — standard HTML for headings, paragraphs, lists, code blocks, etc.
JSON
Use editor.getJSON() to retrieve the content as a ProseMirror JSON document:
Copyconst json = editor.getJSON();
This returns a structured JSON tree representing the document. You can store this in a database and restore it later with editor.commands.setContent(json).
The JSON format is useful when you need to:
Store content in a structured format (e.g. a JSON column in your database)
Transform or analyze the document programmatically
When restoring content, pass it back as the content prop. Tiptap accepts both HTML strings and JSON objects.
Server-side rendering
The editor runs in the browser only — editor.getHTML() / editor.getJSON() are client-side APIs. The recommended approach is:
On the server: Store the HTML or JSON blob (returned from the client's onUpdate) in your database
On the client: Pass it back to useEditor({ content }) when loading the editor
To render editor content on the server (e.g. in a blog post view), use the HTML output with dangerouslySetInnerHTML. Make sure to sanitize the HTML if users can submit content:
Copyfunction RenderContent({ html }: { html: string }) { return ( <div className="prose" dangerouslySetInnerHTML={{ __html: html }} /> );}
For embeds rendered outside the editor, you'll need to replace the custom <div data-type="youtube"> / <div data-type="twitter"> elements with actual iframes or Twitter widgets. Use the data-src / data-tweet-id attributes to construct the embed URL.