Quick start
Install and configure Presence
This quick start provides a summary of a Pitter Patter Presence configuration. For a more in depth explanation, see the Presence Guide. You can also see a fully functional demo in our Github repo.
Configure your backend
npm i @pitter-patter/presence-serverFirst create a
PresenceAuthority.
The code below assumes you have a Redis cluster accessible at REDIS_URL
import {
PresenceAuthority,
PresenceIndicator,
RedisPresenceBroadcastManager,
RedisPresencePersistenceManager,
} from "@pitter-patter/presence-server";
const presenceBroadcaster = new RedisPresenceBroadcastManager({
redisUrl: process.env["REDIS_URL"] ?? "redis://localhost:6379",
});
const presencePersister = new RedisPresencePersistenceManager({
redisUrl: process.env["REDIS_URL"] ?? "redis://localhost:6379",
});
const presenceAuthority = new PresenceAuthority({
persistenceManager: presencePersister,
broadcastManager: presenceBroadcaster,
});Next, create two endpoints. One for clients to submit their presence indicator and one for clients to listen for updated presence indicators.
// Endpoint that clients will use to send their updated indicator to the PresenceAuthority
app.post("/api/docs/:docId/presence/:clientId", async (req, res) => {
const indicator = req.body as PresenceIndicator;
await presenceAuthority.updatePresence(req.params.docId, indicator);
res.status(204).send(null);
});
// Endpoint that clients will use to listen for indicators from the PresenceAuthority
app.post("/api/docs/:docId/presence", async (req, res) => {
const { refs, clientId } = req.body as {
refs: Record<string, string> | undefined;
clientId: string;
};
const presence = await presenceAuthority.listenForPresence(req.params.docId, clientId, refs);
res.status(200).send(presence);
});Configure your frontend
Using React?
If you’re using @handlewithcare/react-prosemirror to render your ProseMirror editor with React,
you should import the presence plugin from @pitter-patter/presence-client/react, instead of
@pitter-patter/presence-client!
npm i @pitter-patter/presence-clientTo configure your frontend editor with Presence, you first add the presence plugin when creating your editor state
import { EditorState } from "prosemirror-state";
import {
presence,
PresenceClient,
receivePresenceTransaction,
LongPollListener as PresenceLongPollListener,
PresenceClientConfig,
} from "@pitter-patter/presence-client";
const state = EditorState.create({
doc: // your initial prosemirror schema and document
plugins: [presence()],
})Then create a PresenceClient. This client uses the endpoints you created above to send and listen for indicators.
// The PresenceListener listens for indicator changes at the
// `/api/docs/:docId/presence` endpoint you created above
const presenceListener = new PresenceListener(
new URL(`/api/docs/${doc.id}/presence`, "http://localhost:3000"),
);
const presenceClient = new PresenceClient({
userId,
sendIndicator: async (indicator) => {
// send `indicator` to the `/api/docs/:docId/presence/:clientId` endpoint you created above
},
receiveIndicators: (indicators) => {
// merge a new set of indicators into your editor state for example
// const newEditorState = oldEditorState.apply(receivePresenceTransaction(oldEditorState, indicators)));
},
listener: presenceListener,
});Tell the PresenceClient to listen for updates
const abortController = new AbortController();
presenceClient.listen(abortController.signal).catch((e) => console.error(e));And send your client's indicator state when it updates
presenceClient.send(state).catch((e) => console.error(e));