Collaboration setup
Deploy the Cloudflare Worker that powers realtime collaboration and wire it to the app with a shared HMAC secret and the WebSocket host.
Realtime collaboration runs on a Cloudflare Worker, not the app server or the Docker stack. Until you deploy that Worker and point the app at it, collaboration stays disabled and the rest of the app works normally.
Components
- The Worker in
apps/collab/notes.ts, configured byapps/collab/wrangler.jsonc. It runs Yjs over a WebSocket and verifies each connection inonBeforeConnect. - The Next app, which signs a room token per note and sends it to the browser.
The Worker and the app share one HMAC secret. The app signs tokens with it, the Worker verifies them. If the two values differ, every socket returns 401 and nothing syncs.
Local development
Run the Worker with wrangler:
bun run party:devIt serves on 127.0.0.1:8787. Set the app env:
NEXT_PUBLIC_PARTYKIT_HOST="127.0.0.1:8787"
COLLAB_AUTH_SECRET="<same value as the worker>"Put the same COLLAB_AUTH_SECRET in .dev.vars (gitignored) so the local
Worker reads it.
Production
Deploy the Worker:
bun run party:deployThe deploy prints the Worker host, in the form
<worker-name>.<subdomain>.workers.dev. Set the secret on the Worker and the
host on the app:
bunx wrangler secret put COLLAB_AUTH_SECRET -c apps/collab/wrangler.jsonc # same value used to sign tokensNEXT_PUBLIC_PARTYKIT_HOST="<worker-name>.<subdomain>.workers.dev"
COLLAB_AUTH_SECRET="<same value as the worker>"NEXT_PUBLIC_PARTYKIT_HOST is inlined at build time. On a prebuilt Docker
image it is frozen, so a self-host image that ships collaboration needs the host
baked in at build. See Self-host with Docker.
Disable
Leave NEXT_PUBLIC_PARTYKIT_HOST blank. This is the default in .env.example.
A non-empty value pointing at a Worker that is not running makes every socket
return 401, so keep it blank unless the Worker is live.
Environment variables
Every variable Skriuw reads, whether it is required, its default, and what stops working when it is unset. Grouped by subsystem, matching .env.example.
Release pipeline
How a Skriuw version becomes a pullable Docker image, what the GHCR publish workflow automates, what stays a manual tag, tag conventions, and the one-time public-package setup.