Rich text
rich_text fields are stored as JSON blocks, not HTML. That way the content doesn't depend on any framework: the API also delivers it converted to markdown and to HTML.
In the dashboard you write in markdown. Through the API (phase 3) you send JSON or markdown.
Document
{
"type": "doc",
"content": [
{ "type": "heading", "level": 2, "content": [ { "type": "text", "text": "Open House" } ] },
{ "type": "paragraph", "content": [
{ "type": "text", "text": "A " },
{ "type": "text", "text": "great", "marks": ["bold"] },
{ "type": "text", "text": " day. " },
{ "type": "link", "href": "https://acton.example", "content": [ { "type": "text", "text": "Sign up" } ] }
] }
]
}
Blocks
type |
Fields | Markdown |
|---|---|---|
paragraph |
content: inline |
A paragraph |
heading |
level (1 to 6), content: inline |
## Title |
list |
ordered (bool), content: items { "type": "item", "content": [blocks] } |
- one or 1. one |
quote |
content: blocks |
> quote |
code |
text, language (optional) |
Block with three backticks |
hr |
— | --- |
image |
asset (ID of a Pluma asset) or src (external URL), and alt |
 or  in its own paragraph |
table |
content: rows { "type": "row", "content": [ { "type": "cell", "content": [inline] } ] }. The first row is the header |
GitHub table: | A | B | and the line | --- | --- | |
Inline
type |
Fields | Markdown |
|---|---|---|
text |
text, marks (optional): bold, italic, code, strike |
**bold**, *italic*, `code`, ~~strikethrough~~ |
link |
href, or entry (ID of another entry, see Links to entries); content: inline |
[text](url) or [text](entry:ID) |
break |
— | Two spaces at the end of the line |
Links to entries
To link to another entry of your site, write [text](entry:12): it's stored as { "type": "link", "entry": "12", … }, a link to that entry, not to its address today.
- Reading with
rich_text=markdownorhtml, it comes out as the entry's path on your site, from its type's page URL:[seeded rye](/menu/rye-seeded). Change the slug and every link follows it, without editing the posts. - If the type has no page URL, or the entry isn't published (with a delivery key), the link stays
entry:12in markdown and becomes#in HTML. - Publishing checks every entry link: the target has to exist and be published, or you get
validation_failedwithlinks to entry:12, which isn't published yet. Publish the target first (in a batch, put itspublish_entryearlier).
Rules
- Markdown → blocks → markdown gives the same document (lossless round trip).
- When reading with
rich_text=markdownorrich_text=html, Pluma images come out with their real URL, ready for your site. Withrich_text=jsonthey stay as"asset": "ID"and the URL is inincludes(withinclude=1). - HTML comes out escaped. Links that don't start with
http,https,mailto,/or#are replaced with#: nojavascript:. - Raw HTML inside the markdown (
<u>,<div>) is stored as text, not interpreted. If your content needs HTML, store it in atextfield with the markdown as is and render it on your site. - Table column alignment (
:---:) is not stored.