Providing new elements via configuration files
- Dominant language
- PHP
- Stars
- 3.4k
- Forks
- 1.2k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 433
Description
## User story
Adding a content element type used to mean registration boilerplate and hand-written Administration components, and there was no clean path for plugins or apps to ship their own. This story makes an element type a single declarative file that core, plugins, and apps all register the same way, with no difference between a core type and a third-party one, and that the Administration can configure without a per-type admin component.
As a developer building for Shopware (core, a plugin, or an app), I would like to declare a new content element type in one YAML file, listing its properties, slots, and metadata, so that the element becomes available everywhere without registration boilerplate or custom Administration code.
As the Administration and AI-assisted page builders, I would like to read every available element type, its typed properties, and its slots from one endpoint, so that I can offer and configure those elements without hardcoding any type.
## Acceptance criteria
- A new element type is one YAML file. Its name is derived from the file path with a source prefix, so name and path can't drift apart and core, plugin, and app types stay distinguishable by source.
- Core, bundles, plugins, and apps register types through the same mechanism, with no difference between a core type and a third-party one apart from the source label.
- Each type declares everything needed to use it in that one file: its display metadata, its configurable properties and their types, its slots, and hints for AI-assisted page building.
- A misconfigured type fails fast with a clear error rather than breaking at render time, and type names stay unique across all sources.
- Plugins can ship types from a custom directory. App types persist on install and update and follow app activation state, appearing or disappearing without a container rebuild and without being deleted on deactivate.
- The full registry is served through a single read API the Administration and other clients can consume.
- The Administration renders a type's editing form automatically from its declared properties, with no per-type admin component.
## Remaining work
The declaration and introspection foundation is delivered in #15746. The outstanding piece of this story is the auto-generated Administration config UI: the Admin consumes the type registry and builds each element's config form from its property types, with no hand-written admin component. The original proposal carried an `adminUI` block (field widget, options, editability, help text) to steer this; the shipped spec dropped it, so the remaining work has to decide whether widget choice is inferred from property types alone or needs a field-hint mechanism reintroduced.
## Open topics and follow-ups
- Versioning of element configurations across updates will be handled in a dedicated follow-up story: how to deal with breaking changes in element configs on update, and how to guarantee forward-compatibility. These are the two open questions raised on this story.
- Whether the typed property map needs richer schema support (for example reusable entity references) is still to be discussed. The original JSON-Schema `configSchema` sketch was set aside in favor of the current flat typed properties.
- Whether to model further optional metadata (preview image, vendor, snippet-based labels) is still to be discussed.
- When resolving the topics above, weigh the earlier element configuration proposal in #3269.
## Technical details
Delivered as a Core element-type registry with compile-time directory discovery, path-derived naming, app-lifecycle persistence, constraint validation, caching, and an introspection endpoint. See #15746 for the registry, the YAML schema, the persister and collision detection, and the API endpoint. The auto-generated Administration config UI that consumes this registry is the remaining work.
## Type defintion suggestion
YAML file
```YAML
# shopware-element: Sw:Product:Card
schemaVersion: "1.0"
meta:
name: "Sw:Product:Card"
category: "commerce"
label: "Product Card"
labelSnippet: "content.elements.product.card.label"
description: "Lorem ipsum dolor sit amet."
descriptionSnippet: "content.elements.product.card.description"
agentDescription: "This component renders simple product information."
icon: "card"
previewImage: "path/to/my/preview/image.jpg"
vendor: "shopware AG"
slots:
- name: "header-top"
maxElements: 4
allowList: []
description: "Slot for the card header section."
configSchema:
$schema: "https://json-schema.org/draft/2019-09/schema"
$id: "shopware://content-elements/sw-product-card"
title: "Product Card Configuration"
type: object
required:
- product
properties:
product:
$ref: "shopware://schemas/entity-refs#/$defs/productRef"
title: "Product"
description: "The product that should be shown in the card."
isProp: true
adminUI:
field: "mt:product:selection"
isEditable: true
isHidden: false
headline:
type: string
title: "Card Headline"
isProp: true
isTranslatable: true
layout:
type: string
title: "Card Layout"
description: "Layout variant for the product card."
isProp: true
enum:
- "box"
- "list"
default: "box"
adminUI:
field: "mt:text:field"
isEditable: true
options:
- value: "box"
label: "content.element.option.layout.box"
- value: "list"
label: "content.element.option.layout.list"
helpText: "This is the layout selection for the product card."
```
Contributor guide
Assessment
This issue has not been assessed yet.