Collaboration for Quoin, operated for you.
Real-time editing, presence and comments on a server you do not have to run, scale, back up or wake up for. The editor and the wire protocol are open. Operating it is the part worth paying for.
Free for 25 people a month and 100 documents. No card.
The bargain, stated plainly
Yours either way
The editor is MIT and on npm. Your documents are plain Yjs state. The wire is y-websocket's protocol, so a client you already have talks to this server, and this server is not the only one that can serve your documents.
What you are paying for
Sockets that survive a deploy. Documents kept across restarts and across instances. Presence that still works when your traffic lands on two machines instead of one. Usage you can read. Somebody for whom three in the morning is their problem rather than yours.
Nothing is held back
No feature of the hosted server is missing from the one you can run. The moment the dashboard is the only way to do something, the open half becomes a demo and this whole argument stops being true, so it does not happen.
The demo, not a video
Running on this service, right now, served from this application rather than a deployment of its own: the editor, presence, comments and the AI assistant. Open it in two tabs and type in both.
The demo, live
The same editor and the same server this page is selling. Open it in two tabs and watch them agree.
Three steps, and the third is nothing
Your application decides who the reader is
Your users never reach us to prove who they are, and we never learn anything about them. Your server mints a short-lived token naming the room, and, if you would rather count people than connections, an opaque id for the reader. The format is an HMAC over base64url JSON, which is this much code.
import { createHmac } from 'node:crypto'; const roomToken = (claims, secret) => { const body = Buffer.from(JSON.stringify(claims)).toString('base64url'); return `${body}.${createHmac('sha256', secret).update(body).digest('base64url')}`; }; // In your own route, once you already know who is asking. roomToken( { room: 'design-notes', exp: Math.floor(Date.now() / 1000) + 300, project: process.env.QUOIN_PROJECT_ID, subject: reader.id, }, process.env.QUOIN_SIGNING_SECRET, );The browser opens a provider with that token
Any y-websocket client will do, because the protocol is y-websocket's. There is nothing of ours to install in the browser unless you want the smaller purpose-built client.
import * as Y from 'yjs'; import { WebsocketProvider } from 'y-websocket'; const doc = new Y.Doc(); const token = await fetch('/api/room-token/design-notes').then((r) => r.text()); const provider = new WebsocketProvider( 'wss://quoincloud.com/api/collab', 'design-notes', doc, { params: { token } }, );There is no third step
Hand the Yjs document to the editor's collaboration extension and you are finished. That part is documented on the editor's own site, which is where everything about the editor lives.
How you leave
Infrastructure that is hard to leave is infrastructure you have to keep, which is not a relationship worth having. Every document exports from the dashboard as the Yjs state a server would hold, and loads back into a plain Yjs document in one call. The wire is y-websocket's, so moving is a change of URL. Both of those are checked rather than asserted: an unmodified y-websocket client syncs through this server, carries presence through it and passes its token the same way, and an exported document opens in a bare Yjs document with nothing of ours involved.
Start on the free tier
25 people a month, 100 documents, 2 projects, no card. At a limit nothing is deleted and nothing already there stops working; what is refused is a document nobody has made yet.