PreviousNext: Experience Builder has pushed the boundaries of what Drupal can do. Here's how we can push it further.
You've probably seen some excitement in the Drupal community around Experience Builder. The current version (0.5.0-alpha1) shows a giant leap forward in Drupal's page building and editing experience.
by lee.rowlands / 8 July 2025Since late 2024, I've been engaged by Acquia to work on Experience Builder. This has been a particularly challenging project, combining many core Drupal concepts, such as the Form, Render, Entity, Plugin and Validation APIs, with newer front-end technologies like React, Redux, RTK-Query, Vite and Astro.
As we approach a beta release, I've been thinking about how we could push Experience Builder even further. Here are some of the things I'd love to work on next.
True multi-user editingCurrently, Experience Builder makes use of hashing to detect editing conflicts. If two users are editing the same page and one of them doesn't have the latest changes, the back end will prevent a user from overwriting another user's changes. This is similar to the 'The content has either been modified by another user, or you have already submitted modifications' error message we've had on content edit forms for a long time.
Unfortunately, this doesn't align with what users expect in 2025. Users are accustomed to multi-user editing experiences, such as Google Docs. Experience Builder has gone to great lengths to focus on building a modern front-end editing experience with React, so getting a 'reload to fetch latest changes' message detracts from that.
Luckily, we're well-positioned to support a multi-user workflow.
In Experience Builder's front-end, when you make a change to the page, you making use of Redux to keep track of the layout and model. Each change triggers a 'reducer' that takes the old state and returns a modified version of it.
Currently, we perform those changes on the front-end and then make either a PATCH or POST request to Drupal to update the preview and store the draft version. When you edit a single component, we make a PATCH request and update only that component.
When you perform any other operation, such as re-ordering a component, deleting a component, or adding a new component, we perform a POST request and update the entire model. Technically, in REST parlance, this is a PUT, but let's not split hairs.
True collaborative editing applications typically use a collaborative editing algorithm. There are two widely used algorithms and a third emerging one.
- Operation Transformation (OT)
- Conflict-free Replicated Data Type (CRDT)
- Event Graph Walker (EG Walker)
Google Docs uses the OT algorithm. It has low memory and storage requirements, but is slow to perform merges. CRDTs are more efficient when it comes to merging, but have higher data storage and memory requirements. EG Walker is an emerging algorithm that combines the best of OT and CRDT, aiming to reduce the data and memory overhead of CRDTs without losing the merge speed.
Because we use reducers to make changes to the front-end, we're already thinking of updates to the model as discrete operations. This should lend itself well to adopting a true collaborative editing algorithm that will allow us to achieve the multi-user editing experience users expect in 2025.
Real-time server-side eventsCurrently, the front-end polls the back-end every 10 seconds to update the list of pending changes. This is because we don't have a way of initiating updates from the server side.
Mercure is a lightweight real-time event server that uses Server Sent Events. Mercure was created by Kévin Dunglas from the Symfony Core team and easily integrates with PHP (there's even a module for it).
Adding real-time events to Experience Builder unlocks a huge number of usability improvements. Not only can we initiate updates from collaborative editing in real-time, we can also get really creative with the user experience and add features like:
- Multi-user presence notifications - e.g. we could show the Avatar of users editing a page in the top bar, which is what Google Docs does
- Highlight components another editor is editing - we could add a visual indicator to a component when another user is editing it
Obviously, we would need to take a progressive enhancement approach to this. We can't make Mercure a hard requirement for hosting a Drupal site. We could add these features when Mercure is available and configured, and silently ignore them when it isn’t.
Client-side preview updatesAt present, Experience Builder does a round-trip back to Drupal to update the preview. This is because for SDC and block components, we need Twig to render the preview. Ideally, we could generate a preview from the user's browser and avoid this latency.
There are two ways we could tackle this.
The first approach is to ship a WASM running Twig. The Twig playground is an in-browser version of Twig that lets you write and execute Twig code. This utilises a WASM running PHP and Twig. If we took this approach, we could likely achieve a feature set very close to that of running Twig in Drupal. Obviously, there are some things we can't do. We would be limited to pure Twig templates that take input and produce output. Modules like Twig Tweak, which let your Twig templates interact with Drupal, couldn't be supported. Luckily, most of the things we're rendering in Experience Builder should largely be pure, such as SDCs and Blocks.
The second approach is a bit more experimental. In my spare time, I've been working on a library called twigCASTer. It takes the token stream parsed from Twig and turns it into a Component Abstract Syntax Tree. The Twig parser is only interested in tokens that it needs to render the output. It takes no position on the hierarchy of HTML. Markup in Twig files is seen as a string, with no context of the DOM tree it may represent. twigCASTer extends Twig tokens to build up a DOM tree whilst parsing the string content. From there, it can be cast into another component language. I've been experimenting with taking this AST and casting it into valid compiled JSX.
It’s still very early days, but I do have a number of test-cases passing where Twig goes in and valid JSX, ready for consumption in the browser, comes out. This is a much more ambitious approach and will be tricky to get right. An obvious shortcoming of this approach would be many Drupal Twig extensions that have no JSX equivalent.
Summing upAre you interested in working on any of these features? Do you have ideas or experience working with the technologies mentioned? Reach out in the Experience Builder channel. Or are you interested in sponsoring work on these features? Get in touch with us to express your interest.