A richtext field shows its content as it reads. Pressing it expands a
TipTap editor into the record’s work area, with the
formatting toolbar.
What it can do
| Group | Controls |
|---|---|
| Text | Style and size, bold, italic, underline, strikethrough, inline code |
| Colour | Text colour and highlight |
| Layout | Alignment, bullet and ordered lists, blockquote, horizontal rule |
| Blocks | Callouts, tables, column layouts, code blocks |
| Links | Insert and edit, with the link text |
| Media | Embedded images and video, resizable |
Media comes from the media library, through an extension point the media plugin fills — so the editor itself knows nothing about where assets live.
What it stores
The document — the node tree — not an HTML string. That is what makes a body’s heading order, its tables’ header cells and the language of a quoted passage into things the system can check. See rich text for the stored shape.
A body written before the editor stored documents is still an HTML string in the column. Opening it seeds the editor, which parses it through its own schema, and the first save commits a document — so content upgrades as it is edited rather than in one migration that has to guess what an unknown tag meant.
It checks as you write
The editor shows the same structural findings the server enforces, while you are still in a position to fix them:
| Finding | Blocks a save |
|---|---|
| A heading that skips a level | Yes |
| A heading above the body’s own top level | Yes |
| An empty heading | Yes |
| A table with no header cells and no caption | Yes |
| A link with no text | Yes |
A lang marker nothing can parse | Yes |
| Link text that says nothing about where it goes | No — advice |
Each one names the accessibility criterion it comes from.
The editor deliberately shows the whole list, warnings included, while the server only refuses the errors. A rule nobody sees until a save fails does not help anyone produce better content — which is the difference between a tool that permits accessible output and one that helps you write it.
Language of a passage
Selecting text and marking its language records a lang on that run, which
becomes a lang attribute when rendered. That is how a quoted sentence in
another language gets announced correctly by a screen reader.
For a field whose whole value is in another language, the content type sets it
instead — see the lang option on fields.
Turning it off for a field
Some bodies are not authored prose — a hand-maintained snippet, an email template, anything you edit as markup on purpose, which a rich-text editor would reformat the moment it opened.
body: field.richtext(), // the editor
raw: field.richtext({ admin: { widget: 'textarea' } }) // a plain textareawidget: 'wysiwyg' is accepted too, so a schema can state the intent rather
than rely on the default.
To also stop the server enforcing document structure on such a field:
raw: field.richtext({
admin: { widget: 'textarea' },
validation: { structure: 'off' }
})Rendering it
The editor stores a tree, so rendering is your front end’s job — walk the nodes
and emit what your framework wants. A documentToHtml helper is available if
you want HTML directly.
No collaborative editing
One person edits a record at a time. There is no real-time collaboration, no presence indicators, no operational transform and no websocket layer — two people editing the same entry will overwrite each other, last save winning.