Problem/Motivation
We know we're going to need to support blocks in our data model - see #3454519: [META] Support component types other than SDC, block, and code components
We also know we're going to need to support SDC components.
In #3454519: [META] Support component types other than SDC, block, and code components we're talking about ways of supporting both. This will require introducing a config entity that wraps a plugin. But we already have that in blocks. And we already have a storage layer that supports blocks - in layout builder.
We also already have prior art for placing SDC components in layout builder via SDC block. This however does not allow storing/mapping SDC props to entity fields. Component blocks however, does support wiring component props (albeit via UI patterns v1) to entity fields. It also makes use of the block API's context integration to support linking to fields in context. This means you can render components based on the author of a node, not just the node. We also know we will need formatter support for entity fields. For example - it's not enough to say 'use this image', we need to be able to say 'use this image with this image style'. Component blocks module already supports this, as well as static props and tokens.
Another side-effect of this approach would be a smoother upgrade path. We already have modules like layout builder browser, layout builder restrictions that deal with block entities. We can support existing layouts in place without needing a slow and complex update path.
But there are limitations in the layout builder data model.:
- It does not support nested layouts
- It does not support asymmetric and symmetric translations
So the experiments so far have only considered a greenfield approach to the data model based on #3440578: [PP-2] JSON-based data storage proposal for component-based page building.
There haven't been any experiments (at least not publicly) that attempt to evolve the layout builder data model to address its limitations.
Proposed resolution
- Write an extension to layout builder section field item/list and swap that class in via an alter hook
- In that class, add two additional columns and a computed property that are the same as the new component tree field in the 0.x branch
- When the new columns are empty, we can assume the data is legacy, and load and transform it from the existing section list column. When we next save this entity, we can write to the new columns, in the new format
- When the new columns are not empty, we can use the new data model
- With this data model in place, we get the translation support desired for XB but with a smooth update path. We also solve the 'how do we support other component types' issue
- With this data model in place, we get nested layout support - the old legacy layouts don't support nesting - but the new model does.
- Adapt the component block module's component block into a new block-type that takes the best of SDC block and wires it up to support entity field mappings
- At present Component block module maps a formatter to an entity field - as XB aims to also support editing we will need to extend that to also support widgets
- Adapt the existing component config entity in the 0.x branch to the same use-case as #3365551: Add the notion of a 'configured layout builder block' to solve a number of content-editor and performance pain points - it will store the default configuration of a block, and the regions it can be used in. This allows the site builder to decide what can be used where.
Remaining tasks
This should be a small scale experiment. Items 1-7 of the proposed resolution need to be done in order to demonstrate it could work.
User interface changes
API changes
Data model changes
Issue fork experience_builder-3456064
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #7
larowlanCrediting those involved in discussions that lead to these ideas - apologies if I've missed people - please ping me
Comment #8
larowlanComment #9
larowlanPushed the block and made a start on the field type changes, more to go next week
Comment #10
catchThis seems very worthwhile to try. I think we know the existing layout builder storage needs to change (even if there are things to work out on what exactly the new storage looks like), so whatever we change it to, we have a data migration issue.
I think we need to rule out a hook_update_N() or post update that loops through every layout-enabled/overridden entity on a site, and all of its revisions, and converts it to the new format. This is whether the new storage is provided by layout builder on a new xb module. Doing the migration in an update would force people to run something that potentially takes hours as part of a minor update of core, which is unworkable for some sites.
An idea I had was a specific migration module that would have an admin page that starts a batch (a bit like the contrib image to media field module). This would give site owners more choice when it happens, but it still requires specifically scheduling the migration, and again potentially hours of downtime. Having to do this would be a major barrier to sites switching over.
The idea here to support legacy storage on read, and automatically convert to the new storage on save, is fantastic. It would allow us to update all sites to the new storage as soon as it's available (whether that's a minor release in layout builder or a new module) with zero downtime. Bulk updates of entities and their revisions could then be done in the background whether via an admin page with batch, on cron, or via drush - potentially can support all three.
Then we can add a hook_requirements() later on that detects non-updated entities and warns the site owner, and remove the legacy support in a major release.
Comment #11
tim bozeman commentedIt is possible though, Layout Builder+ adds nested layout support.

It does so by bubbling up each layout block's section storage recursively and packages it in the main entity's section storage. Kinda like russian nesting dolls.
Comment #12
wim leers@larowlan walked me through the foundations he proposes that would unblock this over at #3454519, specifically in his draft MR https://git.drupalcode.org/project/experience_builder/-/merge_requests/68 — and I'm definitely +1 🤩👏
See #3454519-22: [META] Support component types other than SDC, block, and code components for the write-up of everything we discussed, and this issue depends on all 5 points there, but point 4 in particular.
@catch in #10: see the "JIT" bits in points 4 and 5 of that write-up 😄👍
@larowlan: what's next here? I imagine this would be either blocked on all 5 of the things you called out landing first, or this would become one of those 5?
Comment #13
larowlanYep this is paused for now
Comment #14
wim leers👍
Comment #15
tedbowIs this something that is still be considered? If so it would probably be done before stable, correct?
Comment #16
larowlanClosing in favour of #3462238: Decouple tree storage, introduce tree storage plugins which will allow support for LB/Paragraphs
Will copy the tag over there