Platform
← Patterns

PATTERNS FEATURE

Shared live form

Two people edit one document: field deltas broadcast live over the page's single SSE feed, with echo suppression so the field you type in is never clobbered.

Live demo

Participant A

Edits here broadcast to Participant B.

Editing live ·

Participant B

Edits here broadcast to Participant A.

Editing live ·
platform.collab-form Shared mode Single SSE feed Echo suppression Collaboration as configuration

Shared live form

A collaborative form binds a stable formKey + recordId to a shared draft document. Open it in two browser tabs — or, as in the demo, render two panels bound to the same key on one page — and type. An edit in one appears in the other, live.

This is the Live HTML pillar pushed to its most demanding case: not just the server re-rendering a widget on a timer, but people editing the same truth and seeing each other's changes — all over the one stream the page already has open.

Both panels, one document

The live preview renders two platform.collab-form panels bound to the same formKey/recordId, so a field edited in either panel broadcasts to the other:

twig
{{ ui_page_sse_session_meta('live') }}{{ component('platform.collab-form', {    formKey: 'platform-showcase',    recordId: 'demo',    mode: 'shared',    fields: ['title', 'body'],    title: 'Participant A',}, { content: participant_a }) }}{{ component('platform.collab-form', {    formKey: 'platform-showcase',    recordId: 'demo',    mode: 'shared',    fields: ['title', 'body'],    title: 'Participant B',}, { content: participant_b }) }}

The content slot holds the actual fields — each input carries a data-ui-field-name so the form knows which field a keystroke belongs to:

twig
<label ui-text="label" for="collab-a-title">Title</label><input data-ui-field-name="title" id="collab-a-title" type="text" ui="input" placeholder="Type a title…" /><textarea data-ui-field-name="body" id="collab-a-body" ui="input" rows="4"></textarea>

How it works

  1. The form opens /__ui/form-doc and adopts a server-minted stream id from the page's SSE session — it does not open its own connection.
  2. A field edit dispatches over the event runtime and the change broadcasts back to every subscriber of that shared document over the feed.
  3. Echo suppression: the runtime suppresses the echo of the field you are actively editing, so an incoming broadcast never overwrites the text under your cursor. You see other participants' edits; you never see your own keystrokes bounce back and disturb your caret.

mode: 'shared' is the key — it is what binds the two panels to one document instead of two independent drafts. The live transport argument to ui_page_sse_session_meta('live') opens the stream on load so synchronisation is immediate rather than lazy.

One stream, not a websocket stack

Everything above rides the page's single canonical SSE session (GET /__semitexa_kiss). The collaboration is just another consumer of the same feed that serves deferred fills, live refreshes, and component patches — it does not open a parallel channel.

For honesty about direction: this is a server-broadcast model over SSE, not a bidirectional websocket mesh. Edits travel up through the dispatch path and changes travel down as server-pushed frames. That is exactly the Live HTML shape — the server keeps owning and re-broadcasting truth — rather than a peer-to-peer document CRDT.

When to use it

Reach for a shared form when more than one person (or more than one tab/device for one person) needs to edit the same record and see each other's changes — collaborative drafts, shared settings, a two-person review screen. Because it is a declarative component over the feed you already have, you get co-editing without standing up any new infrastructure.

How it ties to the philosophy

Live co-editing usually means a bespoke websocket stack and a second client-side state architecture — exactly the drift the Live HTML and Region Contract pillars refuse. Here it is one declarative component over the same SSE feed the rest of the UI already uses: collaboration becomes a configuration choice (mode: 'shared'), not an architecture project. The server still owns the document and re-broadcasts truth; no widget grows into its own little SPA.

© Edsger W. Dijkstra:"Simplicity is prerequisite for reliability."

home.html.twigImplementation slice
{{ ui_page_sse_session_meta('live') }}{{ component('platform.collab-form', {    formKey: 'platform-showcase',    recordId: 'demo',    mode: 'shared',    fields: ['title', 'body'],}, { content: field_markup }) }}

How it works

The form opens /__ui/form-doc and adopts a server-minted stream id from the page SSE session — it does not open its own connection. Field edits (each input carries data-ui-field-name) dispatch over the event runtime and broadcast back to every subscriber of the shared document over the one feed; the runtime suppresses the echo of the field you are actively editing so your caret is never disturbed. mode: shared is what binds the two panels to one document; the live transport opens the stream on load so sync is immediate.

Why it matters

Live co-editing usually means a bespoke websocket stack and a second client-side state architecture — exactly the drift the Live HTML and Region Contract pillars refuse. Here it is one declarative component over the same SSE feed the rest of the UI already uses: collaboration as a configuration choice (mode: shared), not an architecture project. It is a server-broadcast model over SSE, not a bidirectional websocket mesh — the server keeps owning and re-broadcasting truth.