Exploring the New “Recipes” Feature in Drupal 10
Recipes are a new concept for Drupal 10 designed to replace the old distribution / install profile approach for sites. Their goal is to uncouple an installation from its base to make installs more manageable and tailored to your site’s specific needs.
A Recipe can be a full-on site install or include content types, roles, content workflow rules, and more specialized packages. This opens the possibility of using several Recipes to “compose” your Drupal site instead of using monolithic distributions which may only do 20% of what you need while including a lot of things you don’t. Like in real life, you can use multiple Recipes to compose your solution, mix and match, and change out the parts you do or don’t want.
For a quick overview, you can watch this great talk from Drupalcon Prague last fall on the initiative:
The Distributions and Recipes Initiative for Drupal 10 is still in its early stages but you can still experiment with them today. We created our first Recipe recently for Drupal 10 — and we’ll show you how we did it.
How Drupal Recipes Save You Time
We started with a barebones install of Drupal and added the modules we wanted with specific configurations for them. We usually start with the “Standard” install profile of Drupal and then disable and change what we don’t like post-install. Also, there are a dozen or so contributed modules we install and configure after the fact to provide a starting point for most of our projects. This can usually take anywhere from 2–4 hours. Recipe(s) help turn that process into a few minutes.
To make a Recipe you need to take the following steps:
- Create a repository to host your Recipe
- Make your project aware of “Recipes” so they can be obtained with Composer
- Install the site using the “Minimal” profile so only core services are enabled
- Apply your Recipe to put the site into the desired state you want
We’ll go over these steps in more detail.
Creating a Repository for Your Recipe
First, you need to adjust your composer.json file. In our example, we started with the standard drupal/core-recommended project template.
For Composer to understand your new Recipe install-type, you need to require the Composer Installer Extender package.
composer require oomphinc/composer-installers-extender:2.0.1
This package lets you define new install-types for Composer so it understands where to place them in the file system when it encounters them
Next, you need to add two entries in composer.json for an install-type and its path:
"installer-types": ["drupal-recipe"],
"installer-paths": {
// existing entries omitted...
"docroot/recipes/contrib/{$name}": [
"type:drupal-recipe"
]
}
Now when you require a Recipe with Composer, it will know to place it into the recipes/contrib directory of your project — like how it treats modules or themes.
Drupal.org does not have an official place to host Recipe projects yet. That’s okay though — you can use Composer to define where your Recipe lives. To do this, you need to have a repository on GitLab or GitHub that contains your Recipe. Under the ‘repositories’ section in composer.json, add your Recipe project location:
{
"type": "vcs",
"url": "https://gitlab.com/kevinquillen/drupal-base"
}
The Recipe is public, you can view it here.
Making Your Project Aware of Recipes
Lastly, you need to add a patch for Drupal core. This initiative is ongoing and not yet merged in, so you need to add the patch so Drupal 10 can use the Recipes we make.
Add the following to the ‘patches’ section of your composer.json:
"patches": {
"drupal/core": {
"Allow recipes to be applied":
"https://git.drupalcode.org/project/distributions_recipes/-/raw/patch/recipe.patch"
}
},
Installing with the Minimal Profile
With that in place, you’re now ready to install and set up your project.
After running “composer install,” you now have a patched Drupal 10 codebase ready to install from. This time, you won’t use the Standard install profile, you’ll use the Minimal install profile:
After proceeding through the install, you’ll have a barebones installation to start from. Our Recipe does the rest of the work.
The Recipe that we've made is straightforward. The configuration it ships with is a selection of all the parts of the Standard Recipe that we want with all our contributed modules and configuration layered in.
Since you configured Composer to recognize what a Recipe is, and where yours is located, you can pull it into your project:
composer require kevinquillen/drupal-base:^1.0
The Recipe contains its own composer.json file with a list of contributed modules it requires. Composer will pull all those dependencies in for you.
The following modules come with our “base Recipe” — foundational modules we use on every project:
- Gin admin theme
- Gin Login
- Memcache
- Pathauto
- Robotstxt
- Metatag
- Config Ignore
- Content Security Policy
- Menu Block
- Redirect
These modules are also configured for best practices in our approach to Drupal development.
Applying the Recipe
When you apply our Recipe, these modules will be enabled and configured for you. The config directory in the Recipe contains values we exported from an existing install so you can re-use them for Recipes as a blueprint.
The patched version of Drupal 10 comes with a command to apply Recipes, which can be run like so:
php core/scripts/drupal recipe recipes/contrib/drupal-base
After about 30 seconds, we get a successful notice that our Recipe was applied:
When you log into the site, you can see that the beautiful Gin admin theme is enabled, your required contributed modules are enabled, and that the configuration supplied with the Recipe has been imported:
For example, Pathauto is enabled and has two common patterns set that we use:
Navigating over to the Config Ignore settings, all our values are present:
This is fantastic. It enables all developers at Velir to kickstart a new project from the same Recipe and enforce best practices with a consistent setup. Also, it reduces the time to set up a new install of Drupal from half a day to just a few minutes.
Recipes Can Adjust Your System When They Install
There are some built-in features with Recipes that make them more flexible than distributions or install profiles. One of them is the ability to import all configuration for a module or only some of its configuration.
In our example Recipe, we imported all configuration for certain core modules, but only a few configuration values for others. It looks like this.
config:
import:
dblog: '*'
image: '*'
media: '*'
media_library: '*'
pathauto: '*'
redirect:
- redirect.settings
- system.action.redirect_delete_action
- views.view.redirect
node:
- views.view.content
user:
- views.view.user_admin_people
gin:
- gin.settings
- block.block.gin_breadcrumbs
- block.block.gin_content
- block.block.gin_local_actions
- block.block.gin_messages
- block.block.gin_page_title
- block.block.gin_primary_local_tasks
- block.block.gin_secondary_local_tasks
The config section of a Recipe does two things. One, it provides a way to import all configuration of a module using an asterisk. This tells the system to import all the base configuration plus any configuration marked “optional” for a specific module.
If you don’t use an asterisk, you can specify which configuration to install instead. For the Redirect, Node, and User modules, we only want specific admin Views to be installed. For the Gin theme, we only want certain blocks installed. Gin ships with a “Help” block configuration value. If we imported that file, it would set a dependency on the “Help” module, which we do not want to enable. Leaving it out of this list above tells the application to skip it.
Being specific in what you do and don’t want to import helps keep a site install to exactly what you want.
What happens though if configuration is installed before your Recipe is applied? There is a way to handle that, too.
Some core modules contain configurations installed by Drupal that you don’t want. This cannot be avoided. An example of this is that when you enable the User module, any site visitor is permitted to register an account.
Recipes can also execute “config actions,” which give you the ability to change existing configuration values that you don’t like. You can change the setting of who can register accounts to Administrator only by using the simple_config_update action. While you’re are at it, you can set the admin theme to Gin, disable the internal cron, and set the admin theme to be used when editing content:
actions:
node.settings:
simple_config_update:
use_admin_theme: true
user.settings:
simple_config_update:
register: admin_only
automated_cron.settings:
simple_config_update:
interval: 0
system.theme:
simple_config_update:
admin: 'gin'
default: 'stark'
When you have all this in a Recipe, it provides a great starting point tailored to what's best for you and your organization.
Recipe Combinations
There is one other aspect of Recipes right now that differentiate them from distributions. You can combine Recipes and use multiple Recipes by referencing them in your Recipe.yml file:
recipes:
- recipe_a
- recipe_b
- recipe_c
This would apply the three referenced Recipes as a part of applying your own Recipe.
This enables the ability for interesting combinations and the power for developers to combine and create larger Recipes for their own needs. For example, picking and choosing features from past projects to roll into a new one. It is usually common to reference solutions from before and ‘grab what you need’ — doing that as a Recipe will make that much easier.
Recipes Will be Discoverable
Perhaps one of the more exciting aspects of this will be that Recipes will be discoverable in the Project Browser area of Drupal when the initiative is completed. This will allow site builders to search for available Recipes that meet their needs and grab what they want, just like they can with modules and themes.
Since Recipes are not just limited to acting like an install profile (as we did in this article), this will promote a myriad of options and reuse in the community for common site needs. People will share content types, entity types, roles and permissions, customized functionality, custom config actions and more that the community produces. The advantage here will be saving time on popular and common configurations so folks can site build or develop faster with the acceleration Recipes provides.
For more on the Distributions and Recipes initiative, you can check out the following:
- Distributions and Recipes Initiative page on Drupal.org
- Recipe docs on GitLab
- Makers and Builders – Distributions and Recipes talk from Drupalcon Prague
Generate a Recipe with Drush
We put together a handy Drush generator so you can generate Recipes using an interactive tool instead of writing out a YAML and composer.json files by hand.
To install the generator, require it with composer:
composer require kevinquillen/recipe-generator:^1.0
You can then use the tool with Drush by entering this command:
drush gen recipe
This will start an interactive prompt in Drush to help you scaffold out a Recipe which helps you quickly learn how they’re made:
At the end, it will generate a Recipe based off your answers with most of what you need. Note that this tool does not implement more the advanced capabilities of a Recipe yet.
Here’s how you can view the tool.
Meet Me at Drupalcon 2023
If you’re attending Drupalcon 2023 in Pittsburgh, PA this June, come see my lightning talk on OpenAI / ChatGPT and Drupal 10. I will also be available in the Velir booth every day to discuss all things AI, Drupal 10, and whatever questions you may have.
Get the Drupal 10 Development Cookbook
Are you curious about how to develop modules, themes, and plugins or how to be a great site builder for Drupal 10?
The "Drupal 10 Development Cookbook" is co-authored by Matt Glaman and me. We cover a wide variety of topics with hands-on examples so you can get up and running with Drupal 10 in no time. These topics include running Drupal locally with Docker-based tools, content modeling, creating custom modules, how to do automated testing, and migrating data into Drupal from various data sources. The book will help you understand how to develop and build modules just like the ones we talk about often at Velir.
You can pick up the book on Amazon as a physical copy or for Kindle.