WordPress 7.0 is officially pushing Real-Time Collaboration into the core block editor, and while the demos look like a dream, the technical reality is a bit of a wake-up call. We’ve been tracking the integration of Yjs for a while now. However, now that it’s landing, every developer needs to understand that this isn’t just a “plugin and play” feature. If your code isn’t ready, you’re going to break the collaborative experience for your users.
I’ve spent enough time debugging race conditions in custom editors to know that syncing state across multiple clients is a nightmare. WordPress is handling this via a CRDT-based system, but there are some significant “gotchas” that will trip you up if you’re still relying on legacy patterns. Specifically, if you’re still using classic meta boxes, you’re effectively opting out of the future.
The Meta Box Conflict: Why Collaboration Fails
The most immediate hurdle is that Real-Time Collaboration is disabled whenever classic meta boxes are detected on a post. This isn’t a bug; it’s a safety mechanism. Classic meta boxes don’t sync through the Yjs document, and allowing multiple users to edit a post while one user is potentially overwriting metadata in a non-synced field would lead to massive data loss.
If you want to keep collaboration active, you must migrate your metadata to the REST API. You need to use register_post_meta and ensure show_in_rest is set to true. Consequently, your UI needs to move into the sidebar via a plugin or a custom block. Here is how I usually handle this registration to ensure it plays nice with the new sync engine:
<?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' );
For more on this transition, check out my previous thoughts on WordPress 7.0 development trends and how the admin is evolving.
The sync.providers Filter: Beyond HTTP Polling
By default, WordPress ships with an HTTP polling provider. While polling is reliable, it’s the “bottleneck” of modern collaboration. It’s slow and puts unnecessary load on the server. Thankfully, the sync.providers filter allows us to swap the transport layer for something more robust, like WebSockets.
In a recent project, we experimented with replacing the default provider to reduce latency. By utilizing the y-websocket library, you can achieve true real-time feedback. The filter allows you to return an array of provider creators that WordPress will initialize when the editor loads. Furthermore, this opens the door for enterprise-grade setups using dedicated sync servers.
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 ] );
Common Pitfalls: Shared State and Side Effects
When multiple people are editing, you can no longer rely on local React state (useState) for data that should be shared. If you copy data from the WordPress store into local state, you’re essentially forking the truth. Updates from other users will hit the store, but your component will remain “stale.”
Instead, always derive your values directly from the store using useSelect and use controlled inputs. This ensures that when a colleague changes a value three timezones away, your input field updates instantly.
Another “war story” gotcha: Block side effects on insertion. If your block auto-opens a modal or triggers an API call when it’s added to the page, that side effect will fire for everyone currently in the session. I’ve seen sites crash because five users were suddenly bombarded with simultaneous API requests just because one person added a block. Always use placeholders and wait for a deliberate user click.
Look, if this Real-Time Collaboration stuff is eating up your dev hours, let me handle it. I’ve been wrestling with WordPress since the 4.x days.
Final Takeaway for Developers
The arrival of Real-Time Collaboration in Gutenberg is a massive step forward, but it requires a mindset shift. Stop thinking about “my local session” and start thinking about “the shared document state.” Migrate your meta, audit your side effects, and consider a WebSocket provider if you’re building for scale. For a deeper dive into the technical specs, the official dev note is essential reading.
Also, if you’re still maintaining older blocks, make sure to check out my guide on Gutenberg 22.7 updates to stay ahead of the curve.
“},excerpt:{raw: