Compound Field (Fieldable Fields)
AI agents wrote most of this code inside a harness of four small open-source tools: Strikethroo, Sift, Kenkeep and Self-review. A human wrote the plans, reviewed diffs and kept the architecture in check. Read how it was built.
Compound Field lets site builders combine the field types they already have into a single field type. A call to action with up to three media images, a link and formatted text becomes one field that you can add to a content type, make multi-value, or whatever you need... it's a regular field!
Each sub-field (a field inside the compound) keeps its widget, formatter, validation and storage schema. The values are stored as columns in the host entity's field table, with no child entities or extra revisions to manage. Data entry and theming work exactly like any other field, and there is no performance penalty like the one Paragraphs introduces.
๐ Create your first compound
See it in action
The call to action from the example above, built and used entirely through Field UI.
Configure a compound
3 min ๐น Defining the compound, its three sub-fields, their widgets and formatters, and attaching it to Article as an unlimited field.
Author and render
2 min ๐น Adding two calls to action to an article, with the Media Library, the link widget and CKEditor 5, and rendering them with a single directory component.
Nest compounds
2 min ๐น A Person compound (name and role) inside a Testimonial compound (quote), attached to Article. Then two testimonials on one article.
What is in the database
A compound lives in a single table, even when it nests other compounds. After the core columns come the link's URI, title and options, one target ID per image, and the value and format of the formatted text.
Features
๐งฉ Any field type
There is no list of supported types: all field types work. A sub-field is an instance of a real field-type plugin, so it gets that plugin's schema, widgets, formatters and validation for free. That includes Address, your custom field type, and a field type written next year.
๐๏ธ One table, no child entities
Entity references and Paragraphs introduce database joins, and that bottleneck gets worse the more content you have. A compound value is a row in the host's table: loading the host loads it, saving the host saves it, and nothing scales but the row count.
๐ ๏ธ Field UI all the way
Define a compound once and attach it to any content type. It appears as its own field type, "Compound field", with the usual label, required and cardinality settings. Each sub-field uses the settings form it came with, AJAX and all.
- Cardinality - The host field can be unlimited. Sub-fields need a finite cardinality because their values are columns, but you can set it high and grow it later.
- Widgets and formatters - Chosen once on the compound, overridable on each field that uses it.
- Nesting - A compound can hold other compounds. The nested values are more columns on the same row, not a reference.
- Composition - Reuse the same sub-fields in several compounds.
- Safe changes - Growing a sub-field's cardinality adds nullable columns. Shrinking it, or removing a sub-field, drops data only after your confirmation. Sub-fields can be renamed and removed on compounds already in use, from Field UI or Drush.
- Integrations - Views, Layout Builder, JSON:API, core Migrate and Drush.
- Converters - Bring existing Paragraphs and Custom Field content into a compound.
Post-installation
composer require drupal/compound_field
drush en compound_field -y
- Grant site builders the Administer compound field permission.
- Go to Structure โ Compound fields โ Add compound field.
- In Manage fields, add sub-fields. Every installed field type is available, including other compounds. Give each one a cardinality.
- Choose widgets and formatters in Manage form display and Manage display.
- On any content type, add a field of type Compound field, pick your compound, and save.
Editors get one field on the node form, with each sub-field showing its own widget. The output is a regular field template, so a template override or a single directory component is all the theming you need.
Structural changes can remove historyRemoving a sub-field with data, or lowering its cardinality, deletes values from current and historical revisions in every field that uses the compound. Keep a database backup and follow the deployment guide.
Requirements
Drupal 11.4+ and PHP 8.3+, with core Field and Field UI. Nothing else. The optional drush compound-field:* commands need Drush 13.
The 1.x branch is pre-alpha: use it at your own risk, and report bugs and feature requests. Configuration and behavior may change between releases, so rehearse upgrades on a copy of your site.
Similar projects
Field Collection, Double Field, Custom Field and Field Union all took serious runs at this problem. The hard part is supporting everything Drupal offers around the data model: revisions, translations, moderation, safe changes under live data, tests and documentation.
- Plain core - Add three multi-value fields and hope the second link lines up with the second image, or promote the group to an entity and take on its storage, revisions and access checks. A compound packs the fields together, so they always line up, without a full-blown entity.
- Paragraphs - Every item is an entity with its own rows, revisions, loads and access checks. Revisions and database bloat grow with your content, and nesting adds joins per level.
- Custom Field - Same storage idea, but its authors write explicit support for each field type's widgets and formatters. If the field type you need is not on the list, you are out of luck.
- Double Field - Two values per field, from its own list of types, with no nesting and no reuse across fields.
There are step-by-step guides to convert Paragraphs, Custom Field and plain fields into a compound, plus a process plugin for core Migrate. Try it on a copy of your site first.
Documentation and support
- Documentation site - Tutorials for site builders, editors and developers, with videos.
- Developer guide - Compound values in PHP, and the JSON:API wire format.
- The article - A walkthrough of the module and the AI harness behind it.
Credits
Built and maintained by e0ipso, with sponsorship from Lullabot. Lee Rowlands' Field Union laid the foundation for this module in 2018.
Depends on
Dependencies of the latest stable release
No dependencies recorded for this project.
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.
Activity
Releases
| Version | Type | Core | Notes | Release date | |
|---|---|---|---|---|---|
| 1.x-dev | Dev | 11 | Sep 16, 2026 |