Use Drupal’s Config Actions API to Spice Up Your Recipes

Exploring how Drupal’s Config Actions API extends recipes with modular, reusable configuration changes for modern site building
Use Drupal’s Config Actions API to Spice Up Your Recipes

The evolution of Drupal recipes has sparked new and powerful ways to manage Drupal configuration. With the introduction of the Config Actions API, developers can now create custom config actions to be used inside recipes, allowing for more dynamic ways to alter config entities. It’s like following a pizza recipe but substituting your own sauce: it opens you up to a wide range of customizations. I’ve been playing with config actions in my own team’s dev work with great success.

In this article, I’ll explore what config actions are, how to use them in a recipe, and how to create your own when your recipe needs an extra kick.

What are config actions and recipes?

Recipes are a new feature in Drupal 10.3 and 11+ that automate the process of installing and configuring modules and themes. They can be applied to assist with new site setups or to add features to existing sites. Recipe authors define YAML-based instructions that enable modules, set permissions, configure fields, create content, and more. They are intended to be reusable with the same predictable results every time they are applied.

Config actions let you update parts of configuration without replacing the whole config object. For example, you can use the config action setRequired on field.field.page.body to make the Basic Page’s Body field required, or use grantPermission to grant a permission to a specified role. Think of config actions as methods you can call from YAML that make a change to the config entity. They power many of the operations inside recipes.

Pizza dough making

Using existing config actions in recipes

set — The most basic way to set a single value in a config entity.

config:
  actions:
    pizza_newsletter.config:
      set:
        property: email_title
        value: This Week’s Pizza Recipes

setMultiple — The plural form of set, this config action sets multiple values in one go.

config:
  actions:
    pizza_newsletter.config:
      setMultiple:
        -
          property: from_email
          value: ${from_email}
        -
          property: cc_email
          value: ${cc_email}

In this example, I’m using ${from_email} and ${cc_email} as input variables, which you can learn more about in the official recipe documentation.

simpleConfigUpdate — Set config properties in the same format as a config file. Try to minimize use of simpleConfigUpdate as it’s expected to be deprecated in the future.

config:
  actions:
    pizza_newsletter.config:
      simpleConfigUpdate:
        email_title: This Week’s Pizza Recipes
        from_email: ${from_email}
        cc_email: ${cc_email}

Those are just a few basic examples to demonstrate how config actions are used. Find a full list of actions in the official Drupal Recipes documentation.

Creating a config action plugin

When existing config actions don’t do what you need, you can create your own actions using the Config Action API. There are two ways to accomplish this: with a plugin class or with an Action Method attribute.

To create a config action with a plugin class, implement the ConfigActionPluginInterface like in this example:

<?php
namespace Drupal\food_newsletter_module\Plugin\ConfigAction;
use Drupal\Core\Config\Action\ConfigActionPluginInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Config\Action\Attribute\ConfigAction;
use Drupal\Core\Config\ConfigManagerInterface;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
 * Set the title for newsletter emails.
 */
#[ConfigAction(
  id: 'setNewsletterTitle',
  admin_label: new TranslatableMarkup('Set Newsletter Title'),
  entity_types: ['newsletter'],
)]
final class SetNewsletterTitle implements ConfigActionPluginInterface, ContainerFactoryPluginInterface {
  ...
}

Here we’re creating a config action called setNewsletterTitle that works for newsletter config entities. It accepts frequency, food, and chef as titles and builds a string that will be used for newsletter email titles.

config:
  actions:
    newsletter.type.pizza:
      setNewsletterTitle:
        frequency: weekly
        food: pizza
        chef: Donatello

This would set the newsletter title to Weekly Pizza Newsletter by Donatello.

Spreading the cheese for pizza making

Creating a config action method

Another way to create a config action is with an Action Method attribute, which is especially useful if you already have a method in a config entity that you’d like to turn into a config action.

<?php
namespace Drupal\food_newsletter_module;
use Drupal\Core\Config\Action\Attribute\ActionMethod;
use Drupal\Core\Config\Entity\ConfigEntityBase;
class NewsletterConfigEntity extends ConfigEntityBase {
  #[ActionMethod(adminLabel: new TranslatableMarkup('Set CC Email'), pluralize: 'setCcEmails')]
  public function setCcEmail($email): void {
    ...
  }
}
config:
  actions:
    pizza_newsletter.config:
      setCcEmail:
        email: Donatello@ninjaturtle.pizza
config:
  actions:
    pizza_newsletter.config:
      setCcEmails:
        -
          email: ${cc_email_1}
        -
          email: ${cc_email_2}
\Drupal::service('plugin.manager.config_action')
  ->applyAction("setCcEmail", "pizza_newsletter.config", ['email' => 'Donatello@ninjaturtle.pizza']);

Developer challenge

The Config Actions API is a powerful addition to Drupal’s configuration management toolkit. When combined with recipes, it enables powerful possibilities for recipe applications. Best practices dictate that recipes create predictable and repeatable outcomes, so keep that in mind when contributing recipes.

If you or your organization maintain contrib modules, chances are they include configuration entities—like those in a config form. Many of these settings need more than a simple setter; they often require value validation, string processing, or other specialized data handling. For your benefit, and for the sites that rely on your modules, consider adding config actions so your configuration entities can be updated correctly as part of a recipe. Before long, this will likely become standard practice—so put in the effort now, and your future self (and your users) will thank you.

Image Attribution Disclaimer: At The Drop Times (TDT), we are committed to properly crediting photographers whose images appear in our content. Many of the images we use come from event organizers, interviewees, or publicly shared galleries under CC BY-SA licenses. However, some images may come from personal collections where metadata is lost, making proper attribution challenging.

Our purpose in using these images is to highlight Drupal, its events, and its contributors—not for commercial gain. If you recognize an image on our platform that is uncredited or incorrectly attributed, we encourage you to reach out to us at #thedroptimes channel on Drupal Slack.

We value the work of visual storytellers and appreciate your help in ensuring fair attribution. Thank you for supporting open-source collaboration!

Note: The vision of this web portal is to help promote news and stories around the Drupal community and promote and celebrate the people and organizations in the community. We strive to create and distribute our content based on these content policy. If you see any omission/variation on this please reach out to us at #thedroptimes channel on Drupal Slack and we will try to address the issue as best we can.

Related Organizations

Related People

Upcoming Events

Latest Opportunities