Integrations & security

Use Uncial from React, Vue, or vanilla JS

React, Vue, and vanilla apps can use Uncial through browser-native custom elements. Register them once on the client, then drop the tags into your markup.

import 'uncial/web-components';
<uncial-editor></uncial-editor>
<uncial-renderer></uncial-renderer>

Configure the elements with JS properties, not HTML attributes: the inputs are structured objects and components that do not round-trip through strings. Editor document updates arrive as a bubbling uncial-change event, because non-Svelte hosts cannot use bind:json.

const editor = document.querySelector('uncial-editor');
Object.assign(editor, { blocks, schema, json: document, attributesController, imageSource });
editor.addEventListener('uncial-change', (event) => {
	document = event.detail;
});

const renderer = document.querySelector('uncial-renderer');
Object.assign(renderer, { blocks, schema, content: document });

imageSource is only needed if your blocks have input: 'image' attributes. It is the same object you would pass to the Svelte Editor; see Let authors add images.

Both elements render into an open shadow root, so page styles do not reach them. Pass Uncial's default CSS through the one reflected attribute, stylesheet (a whitespace-separated list of stylesheet URLs).

import uncialStylesHref from 'uncial/styles?url';
editor.stylesheet = uncialStylesHref;

Store Uncial documents in Wagtail pages

Wagtail is the origin story here: deeply nested StreamFields render as towers of stacked form panels, and headless preview requires real plumbing. The companion uncial-wagtail package replaces that experience — it stores an Uncial document in an ordinary Wagtail page field and mounts this editor inside the Wagtail admin, so editors work in your actual components instead of generated forms. Because the body is just JSON, the document you edit is the document served headless (with a resolved image sidecar) for your frontend to render: no admin-to-frontend translation layer, and preview comes for free.

from wagtail.admin.panels import FieldPanel
from wagtail.models import Page

from uncial_wagtail.fields import UncialField
from uncial_wagtail.schema import UncialEditorConfig


class ArticlePage(Page):
    body = UncialField(config=UncialEditorConfig(allowed_blocks=["wagtail.image"]))
    content_panels = Page.content_panels + [FieldPanel("body")]

See the uncial-wagtail README for the headless API, image reference resolution, and custom block registration.

Render known blocks, validate user content

  • Renderer uses the block registry you provide, so unknown custom blocks are not rendered as trusted components.

  • Built-in rich text links are sanitized to http, https, mailto, tel, relative paths, and hash links.

  • Run validation before publishing or saving user-authored documents.

  • Custom block components and html.render hooks are trusted application code; sanitize any raw HTML or navigation attributes they emit.