Skip to content

Collaborative editing: Make syncing a side-concern instead of a replacement for local state#72114

Merged
youknowriad merged 5 commits into
WordPress:trunkfrom
Automattic:improve/sync-as-side-concern
Oct 7, 2025
Merged

Collaborative editing: Make syncing a side-concern instead of a replacement for local state#72114
youknowriad merged 5 commits into
WordPress:trunkfrom
Automattic:improve/sync-as-side-concern

Conversation

@chriszarate

Copy link
Copy Markdown
Contributor

What?

Instead of effectively replacing the core-data store with a "database" Yjs provider (IndexedDB), this change makes syncing a side-effect of the core-data store, without changing how the entity records are represented and treated within it.

Note

This is the first of a series of modular PRs related to collaborative editing derived from the work in #72040. Not all PRs result in a fully functional editing experience.

Why?

  • The primary motivation for this change is that not all entity record properties should be synced. When all properties are not synced, the simplest path is to continue to represent the entity in the local store.
    • Properties like guid, _links, and modified should not be synced because we want the local codebase to remain authoritative over their values.
    • Properties like content should not be synced because we prefer to sync a derivative property (blocks) instead.
  • A secondary motivation is architectural simplicity. The core-data store continues to function as it does now, and the sync package interacts with it as a (privileged) client.
  • A database Yjs provider (IndexedDB) can be a vehicle for offline editing, but this is not easily implemented when a separate database (WordPress's relational database) is considered the source of truth.

How?

  • In editEntityRecord (core-data actions), do not skip dispatching edits and adding undo records for entities with syncing enabled.
  • In getEntityRecord (core-data resolvers), do not conditionally load the entity record into the store, and invert the order so that the entity is loaded before "bootstrapping."
    • This code change is minor (unwrapping an if/else), but produces a large diff due to the changed indentation.
      963b9796c15a1a44431b3386775e7fe05e5bfd1f96293a8e20f5debae3478bc8).
  • Make sure to call the "register" method on the sync provider.
  • In the entity sync config, introduce a set of synced properties. This set is currently limited to blocks to help navigate syncing errors, but it will be expanded in future PRs.

Testing Instructions

  1. Check out this branch.
  2. Enable the real-time collaboration experiment: Gutenberg > Experiments.
  3. Open a post for editing in two different browser environments.
  4. Use your browser's development tools to remove the post editor lock (see screencast in the next section).

Note: This provider uses requests to admin-ajax.php for signaling and the initial connection is delayed.

Testing Instructions for Keyboard

No UI changes in this pull request.

Screenshots or screencast

pr-1.mov

@chriszarate chriszarate requested a review from nerrad as a code owner October 6, 2025 20:59
@github-actions

github-actions Bot commented Oct 6, 2025

Copy link
Copy Markdown

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>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>

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

name
);
const namespace = postType?.rest_namespace ?? 'wp/v2';
const syncedProperties = new Set( [ 'blocks' ] );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't understand why we need this change here? It feels very ad-hoc?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also what about post types that don't support "content" (so have no "blocks" property)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't understand why we need this change here? It feels very ad-hoc?

It is very ad hoc:

In the entity sync config, introduce a set of synced properties. This set is currently limited to blocks to help navigate syncing errors, but it will be expanded in future PRs.

"Syncing errors" is shorthand for all sorts of edge cases, but the most serious issues are:

  • Rich text attributes need to target the raw property.
  • The status field cannot be synced until it "matures" past "auto-draft", otherwise timing issues can result in the post getting stuck.

I didn't address these in this PR because we have more robust solutions available in other PRs, which I will open shortly. But I can create targeted fixes in this PR if that is desired.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't feel like this addresses my question though. I guess what I'm asking is that before making "blocks" a synced property for a given post type entity, we should first ensure the post type in question supports "content" (which we can do in the supports array no?)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Anyway, it's not a huge concern though but we should be thinking about post types that don't have "content" or "blocks".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, also addressed in a future PR. You can see how we approached this in #72040 in this commit:

Apologies, I will have them all open today and can give you better pointers.

@youknowriad

Copy link
Copy Markdown
Contributor

Thanks for splitting the work into small PRs, this one is good to go :)

@youknowriad youknowriad merged commit c214929 into WordPress:trunk Oct 7, 2025
78 of 80 checks passed
@youknowriad youknowriad deleted the improve/sync-as-side-concern branch October 7, 2025 18:32
@github-actions github-actions Bot added this to the Gutenberg 21.9 milestone Oct 7, 2025
@youknowriad

Copy link
Copy Markdown
Contributor

Note that I sent you an invite to join the Gutenberg team, which means you should be able to use branches instead of a fork and also can merge approved PRs

@youknowriad youknowriad added [Type] Enhancement A suggestion for improvement. [Type] Experimental Experimental feature or API. [Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration and removed [Type] Enhancement A suggestion for improvement. labels Oct 7, 2025
@youknowriad

Copy link
Copy Markdown
Contributor

I invite you to check the different PR practices (labels, merging props...)

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] Experimental Experimental feature or API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants