[META] Configuration management: define needed config entity types

Created on 30 April 2024, about 2 months ago
Updated 20 June 2024, 8 days ago

Problem/Motivation

As a technical builder, I want to be able to work in a separate development environment and move changes to components, templates, or the design system to production. Changes may consist of creation of new components and changes to designs or structure of the components. Ideally this would be managed as part of the configuration management system which is built into Drupal so that the Theme Builder doesn't introduce new processes.

Proposed resolution

  • Basic assumptions
    • Design system = components + style guide
      • The inevitable coupling between the two are the CSS variables.
    • Style guide = set of variables, exposed as CSS variables, used in UI as "design tokens"
    • Components cannot be overridden, only forked (== choosing a new name), but this fork will NOT (automatically) be part of the design system that its original one came from.(IOW: if the design system is updated, any upstream changes to any component will affect this site's default design system too.)
    • Forked components can have their own CSS, but not new CSS variables
  • On a site:
    • 1 active design system
    • optionally: a override of the active style guide (which can override a subset of the default style guide)
  • MVP configurability of a site's design system
    experience_builder.settings.yml
    Active:
    design_system: cocacola
    style_guide_override: christmas
        
  • Eventual configurability of a site's design system
    experience_builder.settings.yml
    Active:
    design_system: cocacola
    Style_guide_overrides:
      default: christmas
      Path_specific:
        node/37: new_years_promotion
      # more advanced stuff: EventSubscriber
        
  • Experience Builder Adoption: new site
    • Theme that depends on `drupal:experience_builder` must be installed
    • … this enables the full potential of Experience Builder
  • Experience Builder Adoption: existing sites
    • Experience Builder module installed, existing theme unchanged
    • … this ONLY enables me to use "element" components (as well as existing Drupal blocks) on the layout canvas
    • (which will look somewhat decent thanks to the existing CSS still applying to these elements)
    • if the active theme contains SDCs, those would be available too.
    • Gradual adoption: If I am actively maintaining my theme, I could choose to convert more things to SDCs, which would then make Experience Builder more useful
  • The Big Default Content Question: instead of referencing content entities and hence depending on them, and hence needing recreate them/ensure they exist on another site, we base64-encode files/images (the 95% use case) to avoid that problem altogether. Additional entity fields/properties that are used such as
    alt, titles, labels could also be exported along with that.

Remaining tasks

User interface changes

API changes

Data model changes

🌱 Plan
Status

Active

Component

Code

Created by

🇺🇸United States tim.plunkett Philadelphia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @tim.plunkett
  • 🇺🇸United States tim.plunkett Philadelphia
  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    There's now a default content import API in core that handles files (courtesy of recipe API) we could make use of that

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    #3: except it doesn't really handle files. @Felix worked on a PoC at https://git.drupalcode.org/project/experience_builder/-/commit/8ecc46f91... — there the managed file is captured in the config itself and recreated on the destination, by using purely the existing config management infrastructure

    The issue description is clearly huge in scope. We should narrow this down to multiple config entity types. Hence making this a meta. Subtasks I propose:

    1. Start with a new config entity type that "decorates" an SDC — only SDCs with such a decorating config entity should be exposed in XB. xb.component.*?
    2. Make it fully validatable + ensure valid config dependencies (on the module providing the SDC), and test that using a ConfigEntityValidationTestBase subclass
    3. Once that exists, allow specifying such a component with a value already assigned to a prop — for example a default image, using parts of the PoC MR's code.
    4. Once that exists, allow specifying whether such a default value is actually fixed — meaning that the user can't change it. For example: a consistent "Christmas hero" component that can be placed in a bunch of places with fixed content. — @lauriii to confirm this is a goal for XB, @Wim thinks he remembers this.
    5. Next: … TBD
  • 🇫🇮Finland lauriii Finland

    Where and/or how would the xb.component.* configuration be created for the Experience Builder components? From DX perspective, it seems ideal that a developer could complete the user story listed in 📌 "Developer-created components": mark which SDCs should be exposed in XB Active within code. Can we achieve that with the proposed solution?

    Once that exists, allow specifying whether such a default value is actually fixed — meaning that the user can't change it. For example: a consistent "Christmas hero" component that can be placed in a bunch of places with fixed content. — @lauriii to confirm this is a goal for XB, @Wim thinks he remembers this.

    There are several related user needs:

    1. As a content creator, I want to create components with static values I can reuse across the site. For example, follow us on social media component which should always have the same content and design regardless of where it's being displayed.
    2. As a builder, I want to create components where some of the values are static and some of them can be filled by content creators. For example, a card with a button, where the button text should always be the same, e.g. "Read more".
  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    #5:

    RE: where/how: the SDC author can't do that — it's a per-site decision.
    RE: related user needs: thanks for those clarifications — that's indeed what I was thinking of when I wrote points 3 and 4 in #4 👍

  • 🇫🇮Finland lauriii Finland

    #6: That's interesting! I think the user stories we have talked about are:

    1. As a front-end developer, I want to have an easy way to expose components from code within the Experience Builder because I want to minimize the time I need to spend to learn a new platform.
    2. As a content creator, I want to be able to use components to build pages from a list of components which has been curated for the context of the site I'm working with so that I don't have to browse through long list of irrelevant options.
    3. As a builder, I want to be able to control which components are available within the Experience Builder so that the content creators are displayed a curated list of components in the Experience Builder.

    This indicates that there should be some aspect of customizability per-site. However, how I was thinking about this was so that a front-end developer could expose a component directly within the Experience Builder, but a builder could revert that decision by hiding the component in the UI.

  • 🇬🇧United Kingdom catch

    However, how I was thinking about this was so that a front-end developer could expose a component directly within the Experience Builder, but a builder could revert that decision by hiding the component in the UI.

    This feels like it could be very error prone.

    e.g. A contrib module adds a new SDC in a new release. It is very similar to a custom SDC that a site already has (maybe even has an identical label).
    Site owner/development team does not notice the new SDC in the list in layout builder until after it's deployed to production.
    Content editors start using the new SDC, either intentionally, or mistakenly because it's similar to another one.
    Once this is discovered, the site owner/dev team now needs to audit all recent content for the new SDC, convert it to the other one, before they can hide it from the UI again.

    vs.

    New SDC goes into an 'available SDCs' list somewhere, and is explicitly enabled by the site owner - now it gets reviewed before anyone starts using it instead of afterwards when it's too late.

    For developers, a 'drush sdc:layout-enable' command or similar could skip having to go into the UI.

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    💯 to what @catch said.

    #7.3 is in conflict with #7.1 in the way it is interpreted in #8.

    For the reasons cited in #8, #7.1 MUST have an asterisk: there still must be a manual action by the (Ambitious Site) Builder to opt in a particular component (SDC).

  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    What catch is saying is also the same as the equivalent LB Add the notion of a 'configured layout builder block' to solve a number of content-editor and performance pain points Active - opt-in instead of firehose++

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺
  • 🇫🇮Finland lauriii Finland

    The current approach for the config entities goes somewhat against the SDC principle which is that everything related to the component should be in a single directory. This way you can move the SDC from a system to another, without having to chase down for additional files outside the SDC. Also, as a frontend developer you know that if you need to make changes to a component, you can always find the underlying code in that directory. It might not be possible to have everything in the *.component.yml, but having a *.experience_builder.yml file there would still be better than storing it in config outside the component.

    What comes to opting-in components, I agree with the general sentiment from @larowlan and @catch that there needs to be a way to curate the components exposed to the page builder. What I'm not convinced is that we should require opt-in on component by component basis. I believe an ideal experience would be something in between a fire-hose and opting in on component by component based. In my mind, that ideal DX would allow exposing components directly from code, without requiring a step in the UI. I believe we should try to enable this while avoiding the fire-hose problem.

    So what if we introduce a concept of categories and tags? This way builder could select either specific components, tags or categories that they want to expose for the content creators. We probably need the concept of categories anyway, in order to group components in the UI.

    By default there would be one category for elements. Rest of the components would be listed as untagged components. Ideally components themselves could specify their category; for no-code components this is in the UI and for code components this is in code. This way sites can choose what is the level on which they want to decide which components can be used by content creators, and you could get rid of the additional step.

    This approach does not have to be specific to choosing which components to allow in the page builder. Individual components need to be able to specify restricted slots too, where they define which components are allowed for that slot. The restricted slots may also want to be able to use tags and/or categories for defining the allowed components. This way the slots become more flexible, because for example in the case that a design system has multiple CTA components, you could allow all different CTA components to be used in a certain slot without having to specify them one by one.

    I proposed this (without as much detail) in 📌 Clarify "components" vs "elements" vs "patterns" Active and @Wim Leers posted some concerns:

    The only way around it I see is generating such a config entity automatically for every discovered SDC

    I'm curious why we'd require a config entity per SDC? I understand that no-code components require a config entity, but why code components require that too?

    A) accept that every SDC ends up in an "untagged" bucket by default and hence we can overwhelm content creators, and allow specifying a tag after the fact

    The untagged bucket might be displayed by default, but most sites would end up disabling it after they've decided how they'd like to restrict components that are available in the page builder.

    B) accept that some SDCs may fail to generate a reasonable preview and can hence confuse content creators, and allow specifying a default value after the fact

    We can probably accept the lack of default values especially given that we can control the starting point ourselves. We can also either come up with ways to generate the default values ourself (i.e. static default values), or by defining some ways to nudge component authors to define them e.g. within development tooling.

    C) accept the field type + widget suggested by #3452497: [MR Only] Edit any component prop, powered by a new FieldForComponentSuggester service, which will power the JS UI as the default, and allow editing after the fact

    I'm not entirely convinced that requiring manual widget selection makes sense for components. Maybe there should be a way to manually override the widget when the one automatically selected doesn't make sense, but I'd imagine this is something that we can automate to large extent for components by setting sensible defaults.

  • 🇬🇧United Kingdom catch

    So what if we introduce a concept of categories and tags? This way builder could select either specific components, tags or categories that they want to expose for the content creators. We probably need the concept of categories anyway, in order to group components in the UI.

    How would that work in the following situation:

    - A site builder includes components from the 'image gallery' tag but not the 'image sliders' tag.

    - A content editor uses a component, provided in code from a contrib module, from within the 'image gallery' tag.

    - The contrib module providing this component realises it's mis-tagged the component, and changes its tag from 'image gallery' to 'image slider'.

    Now the component is no longer allowed, but there is content using it.

  • 🇫🇮Finland lauriii Finland

    #14 I'd imagine the component becomes unavailable to be added to new content. Existing content remains functional both for display and editing, but after deleting the component, it would not be possible to add it back (other than maybe CTRL+Z while still editing the page).

  • 🇬🇧United Kingdom catch

    Re #15 that sounds very unpredictable. It could also go the other way - you opt-out of a tag, then a component moves tag in a contrib module update, and you don't pick it up during QA then suddenly the component is available on production.

    Or you opt-in to the image gallery tag, and a contrib module adds an entirely new image gallery component which you don't want, which you now have to opt out of individually.

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    #14:

    Now the component is no longer allowed, but there is content using it.

    Exactly. That's another reason config is important. Even if we'd be auto-creating that config. Because the config allows us to use the entire config import/export system and dependency system to detect and prevent accidental breakage.

    I disagree with @lauriii's premise in #15.

    @catch wrote the more disastrous example I was thinking of in #16 👍🙏

    The only way I see out of this is to auto-create this "Component" (name TBD) config entity for each discovered SDC, so that the Site Builder doesn't have to do anything to allow advanced Content Creators to use arbitrary components.

    For the reasons cited in #16, there MUST be a triaging ability for the Site Builder to ensure the UX for the Content Creator expected by the Site Builder. Simpler sites may choose not to need this at all. Huge sites with thorough QA may not need it either — in either of those, there might be no Site Builder triaging.
    But for many sites, there would be.

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    Another reason I think we need a config entity: the need to tie SDCs to design tokens — which @ckrina is exploring.

  • 🇫🇮Finland lauriii Finland

    Re #16 I'm wondering if we are overestimating the complexity involved with components in relation to modules. Components (at least ones used via XB, with the exception of elements) would generally not be shipped by modules. This is because components must include both markup and CSS because they are self-contained. For this reason, components are usually specific to a design system, and therefore not shipped by modules.

    I agree that using categories and tags comes with some downsides because you lose some control. Maintaining components one by one for every slot that exists in the system just sounds like a terrible experience. You could still do it if you want to, but you would not be forced to do it.

    The only way I see out of this is to auto-create this "Component" (name TBD) config entity for each discovered SDC, so that the Site Builder doesn't have to do anything to allow advanced Content Creators to use arbitrary components.

    But this would still violate the single directory principle. If we break that principle, it makes it harder to maintain components as well as to share them between sites. Ideally we could do something like https://wordpress.org/patterns/ with SDCs. Requiring additional steps besides copy pasting the directory adds friction to this process.

  • 🇧🇪Belgium Wim Leers Ghent 🇧🇪🇪🇺

    But this would still violate the single directory principle.

    How? If it's auto-generated, it doesn't matter?

    makes it harder to maintain components as well as to share them between sites

    Two sites may want to use the same component but make different data structure choices. One site might be using Drupal core's Media, another might be using just the Image field, and yet another might be using a DAM.

    They could all be sharing the same components, but the way they choose to populate the components' props might be different.

    Requiring additional steps besides copy pasting the directory adds friction to this process.

    If a copy/pasted SDC uses a SDC prop shape already in use on the site, then there would be zero friction. This will be the case most of the time.

    Captured this as

    1. 🛑 (Would address @lauriii's concerns at #3444424-13: [META] Configuration management: define needed config entity types , but merits further discussion — the product requirements are contradictory on this front. ⚠️) Allow specifying default props values when opting an SDC in for XB Needs work specified a default field type + default widget + default value for each component. Flip that around: gather all unique SDC prop shapes, and ask a default field type+widget+value for those. Then, subsequently, we could auto-generate component config entities for all available SDCs. The component config entities could still be valuable to deviate from the default for a particular component.

    at 🌱 [META] Early phase back-end work coordination Active 👍

  • 🇬🇧United Kingdom catch

    Components (at least ones used via XB, with the exception of elements)

    What does 'with the exception of elements' mean?

  • 🇫🇮Finland lauriii Finland

    Elements are low level components that are agnostic to design; e.g. paragraph, container, image, columns, and so on. These are the building blocks for building no-code components. Given that these are design system agnostic, they would be like shipped by modules.

  • 🇬🇧United Kingdom catch

    These are the building blocks for building no-code components.

    OK that makes sense, so essentially components that are so low-level that need zero or very limited CSS.

    Given that, even if it turns out to be the case that modules don't ship higher-level components that often, it seems quite likely that recipes could be shipping low-code components, and depending on granularity/redundancy that could still result in things being available that site builders need to exclude.

Production build 0.69.0 2024