Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/partykit/llms.txt

Use this file to discover all available pages before exploring further.

y-partyserver is an addon library for partyserver that hosts backends for Yjs, a high-performance library of data structures for building collaborative software. It exposes a YServer class (a Durable Object) for the server side, a YProvider class for the client side, and a useYProvider React hook — all wired together over WebSocket for conflict-free real-time sync.
This page assumes some familiarity with Yjs. If you’re new to it, start with the official Yjs documentation.

Installation

npm install y-partyserver yjs

Class: YServer

YServer extends PartyServer’s Server class (which itself extends DurableObject). The simplest possible Yjs backend re-exports YServer directly:
export { YServer as MyYServer } from "y-partyserver";

// then configure wrangler.jsonc and a default fetch handler
// as you would for any PartyServer.
For persistence and custom logic, extend YServer:
import { YServer } from "y-partyserver";
import * as Y from "yjs";

export class MyDocument extends YServer {
  // ...
}

Property: document

document
Y.Doc
The live Yjs document instance for this room. Apply updates to it inside onLoad, and read from it inside onSave.

Static: callbackOptions

Controls how frequently onSave is invoked after edits.
static callbackOptions = {
  debounceWait: 2000,     // ms to wait after last edit before calling onSave
  debounceMaxWait: 10000, // maximum ms to wait before forcing an onSave call
  timeout: 5000           // ms before the onSave call times out
};
callbackOptions.debounceWait
number
default:"2000"
Milliseconds to wait after the last edit before triggering onSave.
callbackOptions.debounceMaxWait
number
default:"10000"
Maximum milliseconds to wait before forcing onSave, regardless of continued edits.
callbackOptions.timeout
number
default:"5000"
Milliseconds before the onSave invocation times out.

onLoad(): Promise<void>

Called once when the first client connects to a room. Use it to load persisted state into this.document.
async onLoad() {
  const content = (await fetchDataFromExternalService(this.name)) as Uint8Array;
  if (content) {
    Y.applyUpdate(this.document, content);
  }
}

onSave(): Promise<void>

Called periodically after edits (debounced via callbackOptions) and when the room empties. Serialize the document with Y.encodeStateAsUpdate and write it to durable storage.
async onSave() {
  await sendDataToExternalService(
    this.name,
    Y.encodeStateAsUpdate(this.document) satisfies Uint8Array
  );
}

onCustomMessage(connection, message)

Override this method to handle custom string messages sent by clients over the same WebSocket connection used for Yjs sync.
onCustomMessage(connection: Connection, message: string): void
connection
Connection
required
The connection that sent the message.
message
string
required
The raw string message. Use JSON.parse for structured data.
import { YServer } from "y-partyserver";
import type { Connection } from "partyserver";

export class MyDocument extends YServer {
  onCustomMessage(connection: Connection, message: string): void {
    const data = JSON.parse(message);

    if (data.action === "ping") {
      this.sendCustomMessage(
        connection,
        JSON.stringify({ action: "pong", data: "world" })
      );
      this.broadcastCustomMessage(
        JSON.stringify({ action: "notification", data: "Someone pinged!" })
      );
    }
  }
}

sendCustomMessage(connection, message)

Send a custom string message to a single connection.
sendCustomMessage(connection: Connection, message: string): void
connection
Connection
required
The target connection.
message
string
required
The string message to send.

broadcastCustomMessage(message, excludeConnection?)

Broadcast a custom string message to all connections in the room, with an optional exclusion.
broadcastCustomMessage(message: string, excludeConnection?: Connection): void
message
string
required
The string message to broadcast.
excludeConnection
Connection
An optional connection to exclude from the broadcast.

Class: YProvider

Import from y-partyserver/provider. Connects a client-side Yjs document to a YServer room over WebSocket.
import YProvider from "y-partyserver/provider";
import * as Y from "yjs";

const yDoc = new Y.Doc();
const provider = new YProvider("localhost:8787", "my-document-name", yDoc);

Constructor

new YProvider(host, room, yDoc, options?)
host
string
required
The hostname (and optional port) of the PartyServer, e.g. "localhost:8787".
room
string
required
The document/room name. Corresponds to the Durable Object instance name.
yDoc
Y.Doc
required
The Yjs document instance to synchronize.
options
YProviderOptions
Full options example:
const provider = new YProvider(
  "localhost:8787",
  "my-document-name",
  yDoc,
  {
    connect: false,
    party: "my-party",
    prefix: "/my/own/path",
    awareness: new awarenessProtocol.Awareness(yDoc),
    params: async () => ({
      token: await getAuthToken()
    }),
    WebSocketPolyfill: WebSocket,
    resyncInterval: -1,
    maxBackoffTimeout: 2500,
    disableBc: false
  }
);

provider.sendMessage(message)

Send a custom string message to the server. The server receives it via onCustomMessage.
provider.sendMessage(message: string): void
provider.sendMessage(JSON.stringify({ action: "ping", data: "hello" }));

Event: "custom-message"

Listen for custom string messages sent from the server via sendCustomMessage or broadcastCustomMessage.
provider.on("custom-message", (message: string) => {
  const data = JSON.parse(message);
  console.log("Received custom message:", data);
});

Hook: useYProvider

Import from y-partyserver/react. Returns a stable YProvider instance tied to a React component’s lifecycle.
import useYProvider from "y-partyserver/react";

Signature

useYProvider(options: {
  host?: string;
  room: string;
  party?: string;
  doc?: Y.Doc;
  options?: YProviderOptions;
}): YProvider
host
string
The server hostname. Defaults to window.location.host.
room
string
required
The document/room name.
party
string
default:"\"main\""
The party path segment.
doc
Y.Doc
An existing Yjs document instance. If omitted, a new one is created internally.
options
YProviderOptions
Any additional YProvider constructor options (see above).
Returns: The YProvider instance.
import useYProvider from "y-partyserver/react";

function App() {
  const provider = useYProvider({
    host: "localhost:8787", // optional, defaults to window.location.host
    room: "my-document-name",
    party: "my-party",      // optional, defaults to "main"
    doc: yDoc,              // optional
    options
  });

  // use provider.awareness, etc.
}

Persistence Example

Combine onLoad and onSave for full persistence across sessions:
import { YServer } from "y-partyserver";
import * as Y from "yjs";

export class MyDocument extends YServer {
  static callbackOptions = {
    debounceWait: 2000,
    debounceMaxWait: 10000,
    timeout: 5000
  };

  async onLoad() {
    const content = (await fetchDataFromExternalService(
      this.name
    )) as Uint8Array;
    if (content) {
      Y.applyUpdate(this.document, content);
    }
  }

  async onSave() {
    await sendDataToExternalService(
      this.name,
      Y.encodeStateAsUpdate(this.document) satisfies Uint8Array
    );
  }
}
onLoad is called once when the first client connects. The document is then kept in memory until the session ends. onSave fires periodically and when the room empties — use it to write to a database or object storage.

Build docs developers (and LLMs) love