Skip to content

Config Management & Recipes

When to Use

Exporting block configuration for deployment, syncing between environments, or using in recipes.

Steps

  1. Understanding block config structure
  2. Block plugins → No exportable config (they're code)
  3. Block config entities → Exportable YAML (block.block.*.yml)
  4. Visibility conditions → Stored in visibility key
  5. Plugin settings → Stored in settings key

  6. Exporting block config

  7. Single config: /admin/config/development/configuration/single/export
  8. Full config export: drush config:export
  9. File location: config/sync/block.block.{id}.yml

  10. Config file structure

    uuid: abc-123
    langcode: en
    status: true
    dependencies:
      module: [system]
      theme: [olivero]
    id: olivero_branding
    theme: olivero
    region: header
    weight: -10
    provider: null
    plugin: system_branding_block
    settings:
      id: system_branding_block
      label: 'Site branding'
      label_display: '0'
      use_site_logo: true
      use_site_name: true
      use_site_slogan: false
    visibility: {}
    

  11. Importing block config

  12. UI: /admin/config/development/configuration/single/import
  13. Drush: drush config:import
  14. Programmatic: \Drupal::service('config.installer')->installOptionalConfig()

  15. Using PlaceBlock recipe action (Drupal 11.1+)

    name: 'Place custom blocks'
    config:
      actions:
        block.block.olivero_myblock:
          placeBlock:
            plugin: my_custom_block
            region: sidebar_first
            theme: olivero
            settings:
              label: 'My Block'
    

Decision Points

At this step... If... Then...
Step 2 (export) Deploying to production Export full config, review diffs before deploy
Step 3 (structure) Referencing content blocks Use UUID in plugin ID (block_content:{uuid})
Step 4 (import) Config already exists Import will update existing; check for conflicts
Step 5 (recipes) Drupal 11.1+ Use PlaceBlock action for cleaner recipe syntax

Pattern

Exporting block config via Drush:

drush config:export --destination=/tmp/config
# Review block.block.*.yml files
cp /tmp/config/block.block.* config/sync/
drush config:import

Programmatic config creation:

use Drupal\block\Entity\Block;

// Create from array
$config = [
  'id' => 'olivero_search',
  'plugin' => 'search_form_block',
  'region' => 'header',
  'theme' => 'olivero',
  'settings' => ['label' => 'Search'],
];

$block = Block::create($config);
$block->save();

// Or load config and modify
$config = \Drupal::configFactory()->getEditable('block.block.olivero_search');
$config->set('region', 'sidebar_first');
$config->save();

Recipe example (recipes/myrecipe/recipe.yml):

name: 'Site blocks'
description: 'Configures standard site blocks'
type: 'Site building'
config:
  actions:
    block.block.olivero_branding:
      placeBlock:
        plugin: system_branding_block
        region: header
        theme: olivero
        weight: -10
        settings:
          use_site_logo: true
          use_site_name: true
          use_site_slogan: false
    block.block.olivero_search:
      placeBlock:
        plugin: search_form_block
        region: header
        theme: olivero
        weight: -5

Reference: core/modules/block/src/Plugin/ConfigAction/PlaceBlock.php, https://www.drupal.org/docs/distributions-modules-and-themes/creating-distributions/how-to-write-a-recipe

Common Mistakes

  • Exporting UUID when not needed → UUIDs change per environment; remove for reusable config
  • Not checking dependencies → Block config requires theme and module dependencies; verify they exist
  • Hardcoding entity IDs in visibility conditions → Use UUIDs or labels for portability
  • Importing config without reviewing diffs → Can overwrite production customizations
  • Not updating config after code changes → Block plugin changes don't auto-update placed block settings

See Also