API

Rich text

Rich text fields are ProseMirror-style JSON documents. The nodes and marks, embedded entries and assets, writing it as Markdown, and the HTML the delivery API can render instead.

1 min read

Rich text fields are ProseMirror-style JSON documents, with TipTap's node and mark names. The entry editor writes exactly this format, and the delivery API answers it by default.

{
	"type": "doc",
	"content": [
		{
			"type": "heading",
			"attrs": { "level": 2 },
			"content": [{ "type": "text", "text": "Intro" }]
		},
		{
			"type": "paragraph",
			"content": [
				{ "type": "text", "text": "Some " },
				{ "type": "text", "text": "bold", "marks": [{ "type": "bold" }] }
			]
		},
		{
			"type": "embeddedAsset",
			"attrs": { "id": "asset_…", "asset": { "url": "…", "alt": "…" } }
		}
	]
}
  • Nodes: paragraph, heading (level), blockquote, bulletList, orderedList (start), listItem, codeBlock (language), horizontalRule, hardBreak, text, embeddedEntry, embeddedAsset.
  • Marks: bold, italic, underline, strike, code, link (href, target, title).

Embeds

Embedded entries and assets are stored by id and checked like references. In delivery responses they are resolved into attrs.entry / attrs.asset, following depth; ones that can't be resolved (unpublished, deleted) are left out.

Writing it as Markdown

The agent API and MCP accept Markdown for a rich text field, and store it as a document; prompt editing reads and writes rich text as Markdown too. Embed an asset with ![alt text](asset:asset_…) and an entry with ![](entry:entry_…).

As HTML

With ?richtext=html the delivery API answers each rich text field as an HTML string instead:

  • images as <figure><img></figure>, other files as links;
  • embedded entries as <div data-entry-id="…" data-content-type="…"></div>, for the site to fill;
  • links only ever have safe URLs (http(s):, mailto:, tel:, # and paths): others are refused when content is saved.

Rendering it

  • React: <RichText document={…} /> from the React SDK, with your own components per node, mark or embed.
  • Anything else: richTextToHtml(doc, { renderEntry, renderAsset }) and richTextToPlainText(doc) from the JavaScript SDK.

On this page

Marks in the margin

  • Note
  • Watch out
  • Updated

Scribes marked doubtful lines in the margin. That practice is called obelism.

Stuck on a step?