Schema

Structured document editor built from schema sections — headline, input, image, video fields, and nested body blocks. Content is stored and exported as JSON with type, meta, and sections.

Use when the editor should follow a fixed CMS schema instead of free-form HTML. Not compatible with the Versions plugin.

Load the bundle

<script src="/assets/redactor/redactor.js"></script>
<script src="/assets/redactor/plugins/schema/schema.js"></script>

Initialization

const app = Redactor('#entry', {
    plugins: ['schema'],
    image: {
        upload: '/api/endpoint/upload-image/'
    },
    schema: {
        schema: {
            type: 'article',
            meta: {
                id: 'demo-1',
                title: 'How to Write Texts'
            },
            sections: [
                {
                    type: 'schemaSection',
                    data: {
                        id: 'headline',
                        label: 'Headline',
                        field: 'headline',
                        required: true,
                        content: 'How to Write Texts'
                    }
                },
                {
                    type: 'schemaSection',
                    data: {
                        id: 'cover',
                        label: 'Cover',
                        required: true,
                        field: 'image',
                        content: {
                            src: '/assets/img/redactor5-photo.jpg',
                            caption: 'Caption',
                            alt: 'Cover photo'
                        }
                    }
                },
                {
                    type: 'schemaSection',
                    data: {
                        id: 'author',
                        label: 'Author',
                        generated: true,
                        value: {
                            prefix: 'By',
                            name: 'John Smith'
                        }
                    }
                },
                {
                    type: 'schemaSection',
                    data: {
                        id: 'tags',
                        label: 'Tags',
                        field: 'input',
                        content: 'writing, tips, seo'
                    }
                },
                {
                    type: 'schemaSection',
                    data: {
                        id: 'body',
                        label: 'Body',
                        children: [
                            {
                                type: 'text',
                                data: {
                                    content: '<p>Most texts on the internet go unnoticed. Readers skim the first few lines and leave within seconds — often because the text fails to communicate value quickly.</p>'
                                }
                            },
                            {
                                type: 'text',
                                data: {
                                    content: '<p>A strong headline and clear opening paragraph help readers decide to stay. Edit the sections above and below to see schema fields in action.</p>'
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
});

Options

  • schema (object)
    • Initial document: { type, meta, sections } or an array of sections. Applied on first load when the editor has no content.
  • headlineBrClass (string | false)
    • default false
    • CSS class added to <br> elements inside headline fields.
  • imageUploadPlaceholder (string | false)
    • default false
    • Placeholder image URL shown in empty image fields.

Sections

Each item in sections is a schemaSection block. The section mode depends on field:

Mode field Value property Editable in editor
Headline headline content (HTML) yes
Plain input input content (string) yes
Image image content (object) yes
Video video content (object) yes
Body omitted or blocks children (block array) yes
Generated omitted value (object) no (read-only)

Common properties

All section types support:

  • id (string) — stable section identifier (data-schema-id).
  • label (string) — label shown in the editor chrome above the section.
  • required (boolean) — marks the section as required in metadata (data-schema-required).
  • generated (boolean) — marks auto-generated content (data-schema-generated).
  • classname (string | string[]) — extra CSS classes on the <section> element (for example scheme-headline).
  • styles, attrs, uid, time, noneditable, nondeletable — standard block metadata (see block docs).

Custom keys not listed above are preserved in section data and round-trip with JSON I/O. Use them for CMS-specific metadata (for example align, category, sortOrder).

Headline

Rich-text title field. Rendered as a large contenteditable area.

  • field - 'headline'
  • content (string) — HTML value. Plain text is fine; the editor stores inner HTML.
  • Line breaks: Enter inserts <br>. Shift+Space inserts a non-breaking space.
  • headlineBrClass plugin option adds a CSS class to <br> elements inside headlines.
{
    type: 'schemaSection',
    data: {
        id: 'headline',
        label: 'Headline',
        required: true,
        classname: 'scheme-headline',
        field: 'headline',
        content: 'How to Write Texts'
    }
}

Input

Single-line plain text field. Rendered as <input type="text">.

  • field - 'input'
  • content (string) — current value.
{
    type: 'schemaSection',
    data: {
        id: 'tags',
        label: 'Tags',
        field: 'input',
        content: 'writing, tips, seo'
    }
}

Image

Image field with upload area and metadata inputs.

  • field - 'image'
  • content (object | string)
    • src (string) — image URL. A bare string is accepted as shorthand for { src: '…' }.
    • caption (string) — caption text.
    • alt (string) — alt text; synced to the preview image.
  • Upload uses editor image.upload (and related image.* options: name, data, convertFormat, convertQuality).
  • imageUploadPlaceholder plugin option sets the placeholder image URL for an empty upload area.
  • Users can paste a URL into Src, drag-and-drop a file, or click the upload box.
{
    type: 'schemaSection',
    data: {
        id: 'cover',
        label: 'Cover',
        required: true,
        field: 'image',
        content: {
            src: '/assets/photo-1.jpg',
            caption: 'Caption',
            alt: 'Cover photo'
        }
    }
}

Video

Video embed field with live preview.

  • field - 'video'
  • content (object | string)
    • src (string) — video URL or embed code. Parsed through the editor embed service (YouTube, Vimeo, direct <video> URLs, etc.). A bare string is accepted as shorthand.
    • caption (string) — caption metadata (stored in JSON; not rendered in the preview).
  • When src resolves to a known embed, a preview (iframe or <video>) is shown below the inputs.
{
    type: 'schemaSection',
    data: {
        id: 'video',
        label: 'Video',
        field: 'video',
        content: {
            src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
            caption: 'Intro video'
        }
    }
}

Body

Nested content area — a regular block editor inside the section. Omit field or set field: 'blocks'.

  • children (array) — nested blocks (text, heading, list, image, etc.) in standard block JSON format.
  • defaultBlock (string | object) — block inserted when the section is empty. Default: { type: 'text', data: { content: '' } }. Pass a type string ('text') or { type, data }.
  • editable (boolean) — force editable mode when both value and children could apply. Default: editable when children is present.
{
    type: 'schemaSection',
    data: {
        id: 'body',
        label: 'Body',
        children: [
            {
                type: 'text',
                data: { content: '<p>First paragraph.</p>' }
            },
            {
                type: 'heading',
                data: { level: 2, content: 'Section title' }
            },
            {
                type: 'list',
                data: {
                    items: [
                        { content: 'Item one' },
                        { content: 'Item two' }
                    ]
                }
            }
        ]
    }
}

Generated

Read-only display section for CMS-generated data. Set generated: true and provide value instead of content or children. The section is not editable.

  • value (object) — key/value pairs rendered as labeled chips. Each value is stored and output as HTML (inner HTML of the chip).
  • Keys are arbitrary — define a schema that fits your CMS (prefix + name for author, publishedAt for dates, etc.).
{
    type: 'schemaSection',
    data: {
        id: 'author',
        label: 'Author',
        generated: true,
        value: {
            prefix: 'By',
            name: 'John Smith'
        }
    }
}
{
    type: 'schemaSection',
    data: {
        id: 'timestamp',
        label: 'Published',
        generated: true,
        value: {
            publishedAt: '2026-06-10T09:00:00Z'
        }
    }
}

A section with value and without children is always read-only. To switch a section from generated to editable body content, replace value with children.

JSON input/output wraps blocks in:

{
    type: 'article',
    meta: {
        id: '123',
        title: 'How to Write Texts',
        authorId: 'user-1',
        publishedAt: '2026-06-10T09:00:00Z',
        updatedAt: null
    },
    sections: [ /* block JSON */ ]
}

Events

This plugin does not emit its own events.

API

setContent

Loads a full schema document (type, meta, sections).

app.schema.setContent({
    type: 'article',
    meta: { id: '456' },
    sections: [ /* … */ ]
});

getContent

Returns the current document as { type, meta, sections }.

const doc = app.schema.getContent();

getSchema

Returns { type, meta } without sections.

const { type, meta } = app.schema.getSchema();

setSchema

Updates type and meta without replacing section content.

app.schema.setSchema({ type: 'page', meta: { id: '789' } });