Insights30 mai 20269 min read

Stop putting AI in a side panel. Put it inside the paragraph.

What we learned building Scriva's streaming AI editor — and why the side-panel pattern that ships in every "AI editor" today is the wrong primitive.

A close-up of a document paragraph mid-typing — the cursor blinks at the end of a half-finished sentence, the next clause materializing in a subtle teal, as if the page itself is writing.

Most "AI editors" you can buy today are a regular editor with a sidebar. The AI lives over there, in its own window, generating text the writer then copies into the document. That's not an editor. That's a chat tool with a paste shortcut. Scriva made us rebuild from a different primitive.

Scriva is an EU tendering firm. They write public-sector proposals — 60-to-200-page documents that have to conform to a procuring authority's structure exactly, cite the right regulations exactly, and ship as a DOCX an auditor can't tell from a human-typed one. Generic AI editors don't work for this job. The team had tried Notion AI, ChatGPT, Microsoft Copilot, and was building proposals the old way regardless.

The brief was specific. The AI had to type into the paragraph the writer was already in. Not into a side panel. Not into a new window. Into the paragraph. With formatting intact, citations anchored to the source PDF, and the entire document exportable to a regulator-grade DOCX in one click.

That's not a chat-tool problem. That's an editor-engine problem.

Why side panels are the wrong primitive

Side panels exist for an honest reason: they're easy. You drop a chat component next to any editor — Slate, Lexical, Tiptap, ProseMirror — and you have an "AI editor." The chat generates text, the user copy-pastes it in. Ship it.

The pattern fails as soon as the work is dense. A proposal writer doesn't want to alt-tab between their paragraph and a chat window. They want to be writing, place their cursor mid-sentence, invoke the AI, and watch the next clause materialize where they were typing. Anything else breaks the writing flow. Anything else asks the writer to context-switch — which means they stop using the AI, which means you've built a tool with a feature nobody touches.

The deeper problem is that side panels can't model decorations. Citations, source attribution, AI-authored ranges — these are properties of the document, not of the chat. If your AI lives outside the editor, your citations can't survive the round-trip. The writer has to manually re-anchor them. They won't.

Why we extracted Plate.js

We chose Plate.js — which sits on Slate — and pulled the relevant portions of Plate into our own codebase via a registry pattern. The editor is self-contained, has zero hidden runtime dependencies except `@/lib/utils`, and we own every extension point all the way down to the rendering loop.

This sounds extreme. It is not. It was three weeks of focused work, and it unlocked everything else. Streaming AI directly into a paragraph requires a custom decoration layer for the in-progress range. Citations need their own marker type. The DOCX exporter needs to walk the document tree and serialize it cleanly. None of these are possible if you treat the editor library as a black box with a thin API.

If you are building an AI editor for a domain where the document model matters — legal, medical, financial, regulator-grade — owning the editor stack is the cost of admission. Wrapping someone else's editor and bolting a panel on works for blogs. It does not work for documents.

A paragraph mid-stream: a sentence half-typed by the user, the AI completion arriving inline in subtle teal, the cursor still blinking at the leading edge.
The AI types into the paragraph. The cursor is the writer's. The teal range is reviewable, lockable, removable.

Streaming as a document operation

The mechanic that makes this feel right is treating the streaming response as a document operation, not a chat message. As Claude tokens arrive, they're inserted into the editor's document tree at the cursor position. Each inserted range is decorated as AI-authored — we render it in a subtle teal so the writer can see what just came from the model versus what they typed.

The writer can accept the range (it loses its decoration and becomes regular text), reject it (cleanly removed), or edit it in place. The document is always the source of truth. The chat history doesn't exist; the document is the conversation.

We use Vercel AI SDK on the client side to manage the stream. The AI service is a separate Python process — heavy retrieval, embedding lookups, Claude orchestration — exposed via SSE. The editor doesn't know or care that the model is anywhere specific; it knows there's a stream of tokens to insert at a cursor.

Citations as decorations, not appendices

Every AI completion is anchored to its source — the originating document and page range. We render this as a small superscript marker in the editor; click it and the source PDF opens at the cited paragraph. Citations survive DOCX export as footnote-style references with full provenance.

This only works because the editor model is decoration-aware. A side-panel AI can't do it; the citation marker has to be inside the document or it gets lost on round-trip. Once again, the editor primitive is doing the work the chat tool couldn't.

If the AI lives outside the editor, the citations can't survive the round-trip. The writer has to re-anchor them by hand. They won't.

On decoration-aware AI

What we'd start with on day one

Three things. Own the editor — extract Plate.js or pick a different vendor where the API gives you decoration access. Treat the stream as a document operation, not a chat message. Anchor every AI output to its source as a first-class decoration, not a citation appendix at the end of the doc.

And budget six weeks for the editor lift, not three. We did it in three and the second three would have saved us downstream rework.

AI editors don't have a chat problem. They have a document-model problem.

Scriva is an active engagement. We can scope an AI-streaming editor for legal, medical, financial, or regulator-grade documents — formats where a side-panel pattern won't survive the deliverable.