Default content and recipes¶
Export sites with their content into a recipe, and install that recipe on another platform with every site, membership and override in place.
Drupal core writes default content as one YAML file per entity and imports it when a recipe is applied. Sites adds what core's format does not carry on its own:
| Data | How it travels |
|---|---|
| A site | The site entity, its settings per environment and its translations. A sub-site depends on its main site. |
| Site types | Configuration: the recipe's config section. |
| Role assignments | site_role_assignment entities; they depend on their site and their user. |
| Stored configuration overrides | site_config_override entities; they depend on their site. The site revision stays out. A path to content in them, like a front page of /node/5, names the content by UUID and depends on it. |
| A site's menu links | menu_link_content entities, exported as members of the site whose menu holds them. |
| An entity's sites | The computed site_memberships field of the entity, origin site flagged. |
| An entity's site overrides | The computed site_overrides field: per language, each site with the values of the fields it pins. |
| Redirects, URL aliases | Their site_id field. |
A site's entity is a dependency of everything that names the site, so an import creates the sites first.
Export¶
drush sites:export-content ../recipes/valtora_demo/content
drush sites:export-content /tmp/hydrion --sites=hydrion,hydrion_uk
sites:export-content writes
every site (or the listed ones), its role assignments and stored overrides,
its member content (with the links of its menus) and site-scoped entities,
and everything those refer to.
Core's content:export command writes one entity the same way. The
Valtora recipe of these docs is such an
export.
Content that belongs to two sites, the second one overriding the title:
default:
title:
-
value: 'Valtora opens a new test center'
site_memberships:
-
site: valtora
canonical: true
-
site: hydrion
site_overrides:
-
site: hydrion
values:
title:
-
value: 'Hydrion pumps at the new Valtora test center'
A reference in an override names its entity by UUID (entity:), as core
writes references, and the referenced entity is exported as a dependency.
Import¶
A recipe imports its content directory when it is applied:
vendor/bin/dr recipe:apply ../recipes/valtora_demo
dr is core's command line tool; it reads the path from the web root.
The import saves each entity as syncing, so the creation-site binding does
not run and the hub does not insist on a site; a migration is treated the
same. Each import brings its memberships; what an import forgets shows on
the Unassigned content report. The
site_memberships field writes the memberships when the entity is saved,
and the overrides are written right after, through
SitesContentOverridesServiceInterface::saveOverride(). A site in the YAML
that the platform does not have is skipped.
Setting site_memberships on an entity in code does the same on save: the listed sites
are added, the others removed, the flagged one made the origin site. Membership
writes are a system decision (Access); the field does not check
the account.
Limits¶
- User accounts are exported with their password hashes. Export demo accounts only.
- User 1 is referred to by ID, never exported.
- An override's paragraphs (nested overrides) and its aspects (the site's URL alias, menu link and sitemap setting for the item) are not exported.
- The
site_membershipsandsite_overridesfields are internal: REST and JSON:API leave them out.
Last updated 2026-10-17