Skip to content

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_memberships and site_overrides fields are internal: REST and JSON:API leave them out.

Last updated 2026-10-17