WordPress 7.0 puts Real-Time Collaboration into the core block editor through Yjs, and the demos make it look effortless. What the demos leave out is that your own code decides whether any of it works. Plenty of perfectly functional plugins will quietly turn the feature off.
I have debugged enough race conditions in custom editors to know that syncing state across clients is unpleasant work. WordPress handles it with a CRDT-based system, which takes the hard part off your hands, but it also assumes your code follows current patterns. Classic meta boxes are the clearest example of what happens when it does not.
Why classic meta boxes shut collaboration off
Real-Time Collaboration is disabled on any post where classic meta boxes are detected. That is deliberate, not a bug. Classic meta boxes do not sync through the Yjs document, so two people editing the same post would each write metadata the other never sees, and one of them loses their work.
To keep collaboration active, move your metadata onto the REST API: register_post_meta with show_in_rest set to true. The UI moves with it, into the sidebar as a plugin panel or into a custom block. This is the registration I reach for:
<?php
/**
* Registering post meta for Real-Time Collaboration compatibility.
*/
function bbioon_register_collaborative_meta() {
register_post_meta( 'post', 'bbioon_subtitle', [
'show_in_rest' => true, // Mandatory for Yjs syncing
'single' => true,
'type' => 'string',
'revisions_enabled' => true, // Highly recommended for audit trails
] );
}
add_action( 'init', 'bbioon_register_collaborative_meta' );
I wrote about the wider shift in WordPress 7.0 development trends, including where the admin is heading.
The sync.providers filter and WebSockets
Out of the box WordPress ships an HTTP polling provider. Polling is reliable, and it is also slow, and it keeps asking the server for changes that have not happened yet. The sync.providers filter lets you swap that transport for something better, with WebSockets the obvious candidate.
On a recent project we replaced the default provider to cut latency, using the y-websocket library. The filter returns an array of provider creators that WordPress initializes when the editor loads, which is also the hook you would use to point an installation at a dedicated sync server.
import { addFilter } from '@wordpress/hooks';
import { WebsocketProvider } from 'y-websocket';
/**
* Custom WebSocket provider for lower latency.
*/
function bbioon_create_ws_provider( { awareness, objectType, objectId, ydoc } ) {
const roomName = `${ objectType }-${ objectId ?? 'collection' }`;
const serverUrl = 'wss://your-dedicated-sync-server.com/';
const provider = new WebsocketProvider( serverUrl, roomName, ydoc, { awareness } );
return {
destroy: () => provider.destroy(),
on: ( event, callback ) => provider.on( event, callback ),
};
}
addFilter( 'sync.providers', 'bbioon/rtc-websocket', () => [ bbioon_create_ws_provider ] );
Shared state and side effects
Once several people are editing, local React state (useState) stops being safe for anything shared. Copy a value out of the WordPress store into local state and you have forked the truth: updates from other users land in the store while your component keeps showing the old value.
Derive the value from the store with useSelect and use controlled inputs. Then a change made by a colleague three timezones away shows up in your input field as it happens.
The one that cost me most: block side effects on insertion. If your block opens a modal or fires an API call when it is added to the page, that runs for everyone in the session. I have watched a site fall over because five users each got a simultaneous API request when one person inserted a block. Use a placeholder and wait for a deliberate click.
If real-time collaboration is eating your dev hours, I can take it off your plate. I have been working on WordPress since the 4.x days.
Where to start
Real-Time Collaboration in Gutenberg asks you to stop coding for your own session and start coding for a shared document. Migrate your meta, audit anything that has a side effect, and look at a WebSocket provider if you are building for scale. The official dev note has the specs.
If you are still maintaining older blocks, my notes on Gutenberg 22.7 updates cover what changed around them.