Marketplaces ship features. Trust marketplaces ship rules.
How we designed CredoGrid's escrow handshake — and why publishing the dispute rule on day one is the trust mechanism, not the feature roadmap.
Read the post
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.

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.
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.
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.

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.
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.”
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.
How we designed CredoGrid's escrow handshake — and why publishing the dispute rule on day one is the trust mechanism, not the feature roadmap.
Read the post
What we learned shipping Verda's POS for a multi-location retail group — and why phase-twoing the cash reconciliation module was the closest we came to breaking the platform.
Read the post