Skip to content

Conversation

@chriszarate
Copy link
Contributor

@chriszarate chriszarate commented Jul 25, 2025

What?

Follow up to #68483

  • Add a filter (core.getSyncProvider) to allow third-party code to load a custom sync provider (transport).
  • Conditionally load the @wordpress/sync package to avoid creating conflicts with third-party code (see below). We have found a new method for avoiding this conflict using a Webpack alias

Why?

There is probably no such thing as a universal transport for collaborative editing. Transports place demands on hosting providers that may require complex configuration changes or present scaling challenges. A WebSocket transport, for example, might be ideal for Host A but unworkable for Host B.

Providing a mechanism for custom sync providers will allow us to ship multiple options side-by-side, letting an administrator choose the best one. It will also allow developers and hosting platforms to inject or configure their own transport, if desired.

Additionally, our choice of Yjs comes with an architectural constraint: Yjs expects to be imported and instantiated exactly once. Therefore, Yjs cannot be imported both in Gutenberg and in a separate plugin, because they are separately bundled, will resolve to separate instances, and will result in the linked issue.

We therefore need a way to conditionally load any sync providers included in Gutenberg. If a custom sync provider is injected, we need to be certain that Yjs is not loaded at all by Gutenberg. This issue has been separately resolved.

How?

  • Introduce a filter (core.getSyncProvider) as the default mechanism for resolving the sync provider. When no sync provider is available, a default "no-op" sync provider is loaded. This removes the need for defensive checks whenever the sync provider is loaded.

Testing Instructions

Note: The collaboration experiment is broken in trunk and remains so in this branch. We will open additional PRs to restore the experiment to a working state, along with additional changes to introduce alternative transports.

  1. Do not enable any experiments and observe the editor working normally without errors, since all effective changes are behind experimental flags.
  2. Enable the "Collaboration: enable real-time collaboration" experiment and observe the error: TypeError: undefined is not an object (evaluating 'config[objectType].fromCRDTDoc'). This is the result of the current non-working state of the experiment. Observe that wp.sync is defined.

Testing Instructions for Keyboard

Same as above.

This filter allows external code to load its own sync provider. This can
be used by both Gutenberg itself and plugins to customize the sync
transport.
@github-actions
Copy link

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: chriszarate <czarate@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

... but dangerously, as I don't fully understand it!
@t-hamano t-hamano added [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible [Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration labels Jul 26, 2025
@chriszarate chriszarate changed the title Allow sync provider to be filtered and avoid Yjs conflicts Allow sync provider to be filtered Jul 28, 2025
Comment on lines +9 to +15
wp: {
ajax: {
settings: {
url: string;
};
};
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these be optional? Otherwise TS will allow consumers of the type to directly access wp.ajax.... without optional chaining.

@chriszarate
Copy link
Contributor Author

Closing in favor of filtering "provider creators" as implemented by #72183.

@chriszarate chriszarate deleted the improve/filterable-sync-provider branch October 10, 2025 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants