Coded components
Coded components are components that embed other components through typed slots. By default, the CLI imports every component as a flat, standalone definition. Composite mode reads those slot relationships and imports the related components together as one hierarchy, so the nesting in your codebase survives into your Contentful manifest.
Composite mode does more than preserve how the hierarchy looks. It imports a parent and everything it slots as a single unit, and it detects problematic relationships, such as slot dependency cycles, before they reach Contentful.
This page explains what coded components are, when to reach for composite mode, where the hierarchy comes from, and how the interactive wizard surfaces it. For the flag list, see Command reference.
When to use composite mode
Import is atomic by default: components are extracted as a flat list with no embedded-component hierarchy. Reach for composite mode when your components nest other components and you want them imported together with that relationship preserved rather than flattened.
Opt in with --composite:
Any composition flag (for example, --composition-map or --composition-agent) implies --composite, so you rarely pass it explicitly once you use a composition source.
The difference between atomic and composite is whether one component can slot another. Atomic imports every component standalone; composite reads the slot relationships between components and imports them together. On top of slots, composite mode adds the grouped review experience, with search, lineage, breaking-change, and cycle tooling the atomic review does not have.
Slots and allowed components
A slot is a typed property on a parent component that holds another component. Each slot carries a list of the component types permitted to fill it. A component that contains only slots is valid; it does not need its own authorable properties.
A parent can slot a component that itself slots others. Composite mode imports the whole chain together, so accepting a parent pulls in every component reachable through its slots as one unit.
Where the hierarchy comes from
Composite mode resolves parent-child relationships from up to three sources. When more than one source describes the same relationship, the higher-precedence source wins:
Typed slots
When your components declare typed slots, composite mode picks up the hierarchy automatically. The extractor reads the slots directly from your source, whether a React prop typed as ReactElement<XProps>, a Svelte Snippet<[XProps]>, or a slot prop annotated with the @allowedComponents JSDoc tag to set its allowed types explicitly. This is the reproducible path and needs no extra configuration:
To capture what typed-slot extraction resolved, write it out with --generate-map. The generated map always mirrors the slots found in your source, so it doubles as a starting point for the composition map below:
Composition map
When your codebase does not declare typed slots, hand-author a composition map and pass it. A composition map is a small JSON file that lists which children each parent slots:
version— the interchange format version. Use1.groups— an object keyed by parent component name. Each value is the list of child component names that parent slots.
Write this file from scratch, or start from a --generate-map skeleton, hand-edit it, then feed it back:
A composition map is the reproducible option for codebases without typed slots, because the same map produces the same hierarchy on every run.
Composition agent
When you cannot declare slots or author a map, a coding agent can infer the hierarchy:
By default the agent writes a sandboxed parser and runs it (--composition-agent-mode parser); pass --composition-agent-mode edges to have it list relationships directly. The agent path is best effort and can vary between runs, so results are cached. Pass --composition-refresh to bypass the cache and resolve from scratch. The agent only finds relationships your code actually expresses; a codebase with no recognizable component definitions yields no hierarchy.
Review coded components in the wizard
Composite mode reworks the wizard’s two review screens, the Scope gate and Final review, into grouped, hierarchy-aware views.
Scope gate
The Scope gate replaces the flat list with a grouped tree whose glyphs reflect which components nest inside which. A counter strip and “Added components” / “Added groups” columns track your selection as you go. Accept the components you want individually, or in bulk; anything you leave untouched is simply not imported:
- Accept or reject any component. Rejecting a parent cascades to its descendants after a confirmation.
- Accept in bulk. The accept-all key seeds every non-cycle component, then pulls in any cycle group reachable from an accepted parent; press it again to reject all. A separate key accepts everything the AI auto-filter did not flag.
- Switch views. Toggle between the grouped tree and a flat list, and expand or collapse all groups at once.
- Trace lineage. Open the lineage panel on a nested component to see its full ancestor tree, with shared-parent and cycle markers.
- Focus a subtree. Jump to a component and filter the view to it plus its transitive ancestors, or filter to only components in a cycle.
- Search. A fuzzy-search overlay filters the grouped list as you type, with autocomplete.
When the AI auto-filter has run, rejected components carry an [×] badge; open the rationale panel on one to read the full, untruncated reason. Cycle members are marked and pinned first. Consult the on-screen legend for the exact keys.
Final review
The Final review step opens on the same grouped sidebar so you can inspect and edit each generated component before push:
- Field editor. Open a component to edit its properties and its slots. For each slot you can edit its allowed components, whether it is required, and its description. The allowed-components picker is cycle-aware, and unselected slot rows show a summary of what they allow.
- Removed-components strip. A strip pinned at the top lists every component that will be deleted from Contentful on push, so removals never happen silently.
- Breaking changes. Filter to only components with breaking changes, and open a breaking-changes panel that renders slot-level mutations in plain text rather than a raw diff.
- Undo/redo and reload. Edits are undoable, group-expansion state and history survive a reload from a saved run, and tabbing away from the field editor with unsaved edits warns you first.
Editing a slot’s allowed components in the field editor is also one of the ways you resolve a dependency cycle, described below.
Slot dependency cycles
A slot dependency cycle is a loop in the hierarchy, where component A slots B, and B slots A, directly or through a longer chain such as Card → Media → Banner → Card. Contentful can’t create components with circular slot references, so the CLI blocks the push before it reaches Contentful and names the components in the loop.
The wizard surfaces cycles at both review screens:
- The Scope gate marks cycle members and shows a guidance line. Cycle members are always accepted or rejected together as a unit.
- The Final review step shows a banner naming the cycle, auto-rejects the cycle members and their slot-ancestors when it opens, and blocks finalize until no cycle remains.
You can resolve a cycle in three ways:
- Break an edge from the cycles panel — open the break-cycle overlay from the cycles panel (
c, thenx), pick a slot relationship to remove, and confirm. This deletes one allowed-component reference and clears the cycle without dropping any component. - Break an edge in the field editor — open a component in the cycle, select the slot that closes the loop, and remove the offending entry from its allowed components. This has the same effect as the overlay, edited by hand.
- Reject a member — reject one of the components in the cycle, which removes it from the import along with the loop.
The recommended workflow is to accept the cycle members together into the Final review step, then break an edge, either from the cycles panel or by editing a slot in the field editor, so you keep every component and only drop the one relationship that closed the loop.
On the headless path, pass --auto-reject-cycles to automatically exclude the components in a cycle and continue. Without it, a headless run that hits a cycle refuses to save or push and names the offending components:
Run coded components headless
Composite mode works on the headless path for CI and non-interactive shells. Pass --composite (or any composition flag) alongside your automation flags:
The composition flags forward to the extraction step, so the hierarchy resolves the same way it does interactively. Atomic remains the default, so a headless run with no composition flag imports a flat list.
Next steps
- Import components — The guided walkthrough of the import wizard.
- Command reference — Every composition flag on
experiences import. - Run the pipeline step by step — Run each stage as an individual command.
- FAQ — Common questions, including atomic versus composite and cycle resolution.