# Run a collaboration server

> Choose a provider and connect room access, storage, and recovery before deployment.



The [two-editor example](/editor/collaboration/connect-two-editors) already runs a Hocuspocus server. Keep it for local
development. Before deployment, choose who operates the provider and how rooms are authorized, saved, and recovered.

## Run the server separately [#run-the-server-separately]

The [collaboration example](https://go.superdoc.dev/examples/collaboration) pins Hocuspocus 2.15.3. Its `pnpm dev` command
starts both the browser app and server. You do not need a second server process.

To run only the server, stop `pnpm dev`, then run this from the example directory:

```bash
pnpm exec tsx server.ts
```

The example listens on port `1234` and keeps rooms in memory. Restarting the process clears them. With no storage integration, unloading a room after its last editor disconnects also loses its state.

Start the browser app separately with `pnpm exec vite`, or return to `pnpm dev` after stopping the standalone server.

Use the [two-editor walkthrough](/editor/collaboration/connect-two-editors#2-open-alex-and-sams-editors) to check the
connection. For storage, pass `COLLABORATION_STORAGE_DIR` to the server command. For the access example, pass
`COLLABORATION_DEMO_AUTH=1` to the server command and `VITE_COLLABORATION_DEMO_AUTH=1` to the Vite command.
The default commands enable neither storage nor access checks.

## Prepare for production [#prepare-for-production]

### Choose a provider [#choose-a-provider]

Hocuspocus is the local example's default, not a requirement. The document's `collaboration` field accepts these targets through `DocumentCollaborationConfig` in the [preview API](/editor/collaboration/connect-two-editors#configure-your-application):

| `providerType`  | Room and connection                     | Authentication                                  |
| --------------- | --------------------------------------- | ----------------------------------------------- |
| `'hocuspocus'`  | `documentId` and `serverUrl` (or `url`) | `token` or string `params`                      |
| `'y-websocket'` | `documentId` and `serverUrl` (or `url`) | String `params` forwarded to your server        |
| `'liveblocks'`  | `documentId` or `roomId`                | Exactly one of `authEndpoint` or `publicApiKey` |

For Liveblocks, use an authenticated endpoint when access must be checked per room; a public key does not provide that check. Configure the chosen provider's server or service before pointing the editor at it. SuperDoc owns the browser connection and local shared state; pass connection settings, not an external `{ ydoc, provider }` pair. To keep an existing provider setup or your own connection code, see [Use your own provider](/editor/collaboration/use-your-own-provider).

### Authorize access [#authorize-access]

The minimal server deliberately has no authentication or durable storage. Before deployment, authenticate the WebSocket connection, authorize each room, persist room updates, set connection and document limits, and define backup and recovery behavior in the server layer.

[Control access to a room](/editor/collaboration/control-room-access) demonstrates credential validation and per-room permission checks. Your server owns authorization; browser controls and display identity do not enforce it.

### Initialize the document [#initialize-the-document]

[Initialize a shared document](/editor/collaboration/initialize-a-document) explains who imports the DOCX, when to create or join, and how browser and backend initialization differ. The Hocuspocus server transports and stores shared state; it does not import the DOCX itself.

### Coordinate initialization and retries [#coordinate-initialization-and-retries]

Follow [create a room safely from your backend](/editor/collaboration/coordinate-room-creation) for a step-by-step setup and error-handling guide.

If initialization stops partway through, do not let multiple clients independently retry `create`. For automatic recovery, your server needs an authoritative, durable record of the document's source revision, current room ID, initialization state, and attempt number. Use it to:

1. Reserve one initializer for a document and source revision; give only that attempt permission to write the initializing room. A second request waits rather than becoming another creator.
2. Check the current attempt when admitting **every incoming document write**, including synchronization writes. On takeover, prevent and drain writes from the old attempt before allowing the new one. A connection-time authentication check alone cannot revoke an already-connected creator. If you run several server instances, they must use one authoritative room owner or a shared, atomic admission boundary.
3. Let the sole replacement attempt retry the existing room only when it is safe to resume. Otherwise leave the partial room untouched. If it was never available to editors and you retained the source DOCX, initialize a new, unpublished room ID. If edits or storage state are uncertain, stop and recover the authoritative state instead of resetting from the DOCX.
4. Publish the document-to-room mapping and admit editors only after a fresh connection validates the completed room **and** the server confirms durable storage. Test simultaneous retries, a delayed old creator, a disconnect during seeding, restart and restore, and an existing room with edits against your chosen provider.

The local example's optional access check validates an identity and room **at connection time**; it does not reserve an initializer or fence later writes. Its optional file storage is also a development example, not a coordinated recovery service. Provider hooks differ: test the write-admission boundary with your provider before relying on this pattern in production.

### Persist the room separately from DOCX files [#persist-the-room-separately-from-docx-files]

[Save and restore a room](/editor/collaboration/save-and-restore-a-room) shows how to store binary Yjs state, restart the server, and reopen with edits intact. It also explains why DOCX exports and presence are separate from room storage.

If your application starts with a local document, [upgrade it to collaboration](/editor/collaboration/upgrade-a-document) when someone invites another person to edit.
