feat(webapp): the editor joins the document the hub is holding - #242
Merged
Merged
Conversation
The client stops being a Yjs provider. y-websocket replaces the hand-rolled SSE-down/POST-up transport on hubs that hold the document, which buys the part that was hand-rolled badly: a state-vector handshake instead of replaying the entire room log on every reconnect, and backoff that is somebody else's problem. y-websocket rather than @hocuspocus/provider, which the plan named: ygo speaks y-websocket natively and Hocuspocus only behind a server flag, so this is one fewer thing that has to agree. The client is TOLD, not left to guess. /api/config carries collab.held, because a hub too old to serve the route and a proxy that refuses to upgrade a websocket fail in exactly the same way — and guessing wrong means either an editor waiting for a document nobody is going to send, or two clients seeding two documents of one file. Editor and VisualEdit read it through useConfig rather than a prop threaded down four components; it is cached with staleTime Infinity, so it is a cache hit. Nothing seeds client-side any more on that path: the hub built the document from the file before anyone attached. The seed claim, its grace timer and the blank-document failure it papered over are all unreachable there. The relay's own update and awareness POSTs go silent on the held path. The socket carries both, so posting them as well was the same bytes twice at a route that only serves GET — which is exactly how it was found, as 405s in a browser console. Both transports still live in collab.ts. Deleting the relay is Stage 4, which is what "the old relay stays reachable for a release" means in practice. Verified end to end with a browser, not only in tests: websocket opens, editor mounts, no console errors. 25 editor e2e pass, including two people editing different paragraphs of one document and a teammate landing in it from a pasted URL. Stage 2 of docs/collab-provider-prd.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
y-websocketreplaces the hand-rolled SSE-down/POST-up transport when the hub holds the document.y-websocket, not@hocuspocus/providerThe PRD named Hocuspocus.
ygospeaks y-websocket natively and Hocuspocus only behind a server flag — so this is one fewer thing that has to agree, for the same gain. Recorded as a deviation in the PRD.The client is told, not left to guess
/api/confignow carriescollab.held.A hub too old to serve the route and a proxy that refuses to upgrade a websocket fail in exactly the same way. Guessing wrong means either an editor waiting for a document nobody is going to send, or two clients seeding two documents of one file. The hub knows; it says.
EditorandVisualEditread it throughuseConfigrather than threading a prop down four components —staleTime: Infinity, so it's a cache hit.Two things that had to go quiet
Still here, deliberately
Both transports live in
collab.ts. Deleting the relay,onSoloand the compensations is Stage 4 — this is what "the old relay stays reachable for a release" means in practice.Verification
Driven with a real browser as well as the suite, because three of the failures on the way here were invisible to unit tests: a route that didn't match the URL
y-websocketbuilds, a client dialling the relay's path, and a hub still serving a bundle compiled before any of it existed.🤖 Generated with Claude Code