Recipes: the Future of Drupal Site Building | GovCon 2024

mandclu 369 views 52 slides Aug 14, 2024
Slide 1
Slide 1 of 52
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52

About This Presentation

Recipes are a new capability for Drupal, allowing sites to add robust features in just a few clicks. Learn about what we can use today, what's in progress, and how you can help!


Slide Content

Recipes:
The Future of Drupal
Site Building
Martin Anderson-Clutz
Senior Solutions Engineer, Acquia

DRUPAL4GOV.US
Martin Anderson-Clutz
@mandclu
@[email protected]

DRUPAL4GOV.US
2024
Drupal
GovCon
Sponsors

Agenda

Why recipes?1
The big news2
Anatomy of a recipe3
Applying recipes4
What we’re working on5
4
Live demo - let’s get cooking!6

Why recipes?


Distributions and
install profiles
have some issues

●They are difficult to keep updated
●They cannot be added after starting
your project
●They can't be mixed and matched with
other sets of functionality
●They are hard to discover before you
install Drupal
The problem:
6

Recipes

●A lightweight way to quickly add
configuration to your site
●They can install modules but do not
have any code of their own
●Composable from other Drupal recipes
●Applied to Drupal sites, they are not
installed
●Easy to share
●Do not lock sites in
The solution:
7

The
big
news


Phase 1 of the
roadmap is
complete!

The phase one goal was to create the ability
to apply an arbitrary recipe to a Drupal
install. Phase two is now on the works!
The Big Update
Released in Drupal
10.3 and 11 as an
experimental API
9

Anatomy of a recipe
10
●Recipe class to read recipe.yml and composer.json
●Enable a recipe to apply other recipes prior to by
applied itself
●Create recipe runner to process drupal-recipe
recipe.yml files to install listed drupal extensions
without their configuration entities
●Extend recipe runner to allow recipe.yml to select
configuration from installed modules
The roadmap - phase 1

●Extend recipe runner to create
configuration provided in the recipe's
/config folder
●Add the ability to define configuration
actions in recipes
●Extend recipe runner to create content
provided in the recipe's /content folder
●Add configuration actions API

Timeline of recipes

DrupalCon Portland 2022:
Dries presents the idea of
starter templates to help
ambitious site builders to quickly
and easily build out solutions
DrupalCon Prague 2022:
Alex Pott demonstrates a
proof of concept that
harnesses yml files to extend
what we already have in
config to create a recipe
2024:
After months of work and QA
by many contributors, the
Standard Drupal Profile as a
recipe is completed
May 2022 Aug 2024
2022 to 2024:
The Config Actions API is added
in order to allow us to
manipulate config in various
ways and has been evolving
continuously
2024:
Config validation is
introduced, allowing us to
roll back the recipe if the
configuration doesn’t
validate properly.
11
2024:
Phase 1 is completed and
the MR is created to add
Recipes to core

Phase 2 begins
2024:
Minimal and Umami
profiles are also
converted into recipes
2024:
Drupal 11 is released,
containing many more
configuration actions

Anatomy of 

a recipe


config
content
composer.json


recipes
install
config:import
config:actions



Anatomy of a recipe
13
recipe.yml
●recipes
●install
●config:import
●config:actions
{…}

14

●Set type as drupal-recipe
●Add module, recipe, or theme
dependencies
●Suggest recipes that users
might want to apply

Anatomy of a recipe
15
{
"name": "fourkitchens/sous-paragraphs" ,
"description": "A collection of recipes and
configuration for Sous with Paragraphs." ,
"keywords": ["recipe", "Drupal recipes",
"drupal recipe"],
"type": "drupal-recipe",
"require": {
"fourkitchens/sous-content-types" : "dev-main",
"fourkitchens/sous-paragraph-types" : "dev-main",
"drupal/paragraphs_features" : "^2.0@beta"
},
"suggest": {
"fourkitchens/editorial" : "A default editorial
workflow."
}
}



composer.json


name
description (optional)
type (optional)
●Groups related Drupal
recipes together.
recipes (optional)
●List other recipes to be
installed with it.
Anatomy of a recipe
16
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types


recipe.yml


install (optional)
●List modules or themes
to install, if they are not
already
●During the install, simple
configuration from the
new modules are
imported



Anatomy of a recipe
17
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types
install:
- paragraphs_ee
- paragraphs_features




recipe.yml


config:import
●Import all available config
from a module: “*”
●Specify which
configuration you want to
import
●If you don’t include
instructions here, only
simple config will be
imported




Anatomy of a recipe
18
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types
install:
- paragraphs_ee
- paragraphs_features



recipe.yml

config:
import:
paragraphs_ee: '*'
paragraphs_features:
- paragraphs.paragraphs_type.cta

config:actions

An action has 3 parts:
1.Configuration entity id
2.The action: must be one that's
declared for the entity type of
the configuration entity
3.Action arguments, depending on:
a.number of arguments that
the action takes, and
b.whether the action is in the
singular or plural form





Anatomy of a recipe
19
name: 'Sous Emulsify'
description: 'A recipe that installs Emulsify
dependencies and sets Emulsify as the default
theme.'
type: 'Site'
install:
- components
- emulsify
- emulsify_tools
config:
actions:
system.theme:
simpleConfigUpdate:
default: emulsify
recipe.yml


#[ConfigAction(
id: 'permissions_per_bundle ',
entity_types: ['user_role'],
deriver: PermissionsPerBundleDeriver::class ,
)]
final class PermissionsPerBundle implements
ConfigActionPluginInterface,
ContainerFactoryPluginInterface {
// Class properties and methods.
}
Config actions API

There are two sets of actions currently
supported by the API:
1.Actions that can be applied to
configuration of any configuration
entity type
2.Actions declared for methods of
specific configuration entity types
○Created by adding PHP attributes
to a method declaration


Anatomy of a recipe
20

simpleConfigUpdate
●It can be used to make updates to any
configuration value
createIfNotExists
●It can be used to conditionally create a
config entity
setComponent
●Add a component (e.g. field) to a
configuration entity
Anatomy of a recipe
21
create
●It can be used to create a config entity.
setThirdPartySetting
●Allows the recipe author to set third-party
settings values for any config entity that can
have third-party settings
●Helpful for modules like Layout Builder and
Scheduler that use these settings to provide or
change functionality.
Globally applicable entity actions

And more!

grantPermissions
Config entity type: role
●Allows you to grant permissions to a role

addNodeTypes, addTaxonomyVocabularies
Config entity type: workflows
●Allows you to add bundles into your
content moderation workflow
Anatomy of a recipe
22
addToAllBundles
Config entity type: field
●Allows you to add a field to all content types
●If the field already exists on a content type, it will
skip that content type
addItemToToolbar
Config entity type: editor
●Allows you to add a button to a CKEditor5
toolbar
Config entity actions

And many more!

Add the same permission(s) to all user roles
actions:
user.role.*:
grantPermissions:
- 'access content'
Affect every view display of every content type
actions:
core.entity_view_display.node.*.*:
setComponent:
name: field_tags
options:
type: entity_reference_label

Anatomy of a recipe
23
Change settings on every instance of a field
actions:
field.field.media.*.field_tags:
simpleConfigUpdate:
foo: bar
Create a view display (i.e., enabling a view
mode) for every content type
actions:
core.entity_view_display.node.*.foo:
createIfNotExists:
# The contents of the view display here...
Config entity wildcards


Idempotency
You should be able to reapply a recipe to the
same site an unlimited number of times
●Some config should be provided using
config actions like createIfNotExists
●Will probably need testing
Anatomy of a recipe
24
Keep granular
Better to have a collection of recipes
●Apply other recipes that are dependencies

Publish!
Directly to Packagist, or to drupal.org as a general
project
Recipe best practices


Anatomy of a recipe
25
●A Drupal recipe can have a content
directory. All content in this directory will be
created after the configuration is installed.
●For this, functionality has been taken from
the default_content module and added
to core. Specifically, the functionality that
imports the content files is being added to
core. Currently if you want to generate the
content files as YAML that are needed to
make this work, you need to use the
default_content module.
Content

image?

Anatomy of a recipe
26
●Export content as YAML from a Drupal
project using the default_content module
●Add those YAML files to the /content
folder in the structure that
default_content generates
●The content will be validated and
imported when the recipe is applied
Add content 

to a recipe

image?

27

28

Applying
recipes


How to apply a recipe

Applying recipes
30

> php core/scripts/drupal recipe core/recipes/standard -v

> ddev exec -d /var/www/html/web php core/scripts/drupal recipe
../recipes/events

> drush recipe ../recipes/events

Recipe runner
order

1.Apply other recipes
2.Install modules and themes
3.Import specified configuration
4.Import provided configuration
5.Apply configuration actions
6.Import content



Applying recipes
31

RECIPES in core
Recipes are conceived as
composable, with any
given recipe often
requiring a chain of other
recipes. But there's little
practical sense as yet of
just how this would work,
or of what recommended
patterns might be.
32
Core install
profiles as sets
of recipes

The process of converting the standard,
minimal, and umami install profiles to recipes
allowed us to discover how a set of recipes
can be composed to give us a specific result.

CLI install of Drupal 

using recipes

Drupal can now be installed from a recipe
without the need for an install profile!



RECIPES in core
33

> php core/scripts/drupal quick-start core/recipes/standard

RECIPES in core
if a site that used
Minimal initially
applies any given
recipe from Standard,
it should end up with
something new that is
ready to use.
● article_content_type
● page_content_type
● feedback_contact_form
● basic_html_format_editor
● full_html_format_editor
● editorial_workflow
● image_media_type
● document_media_type
[and more]
34
What recipes make up
Standard-the-Recipe?


Umami install profile
as a set of recipes

●Converting Umami was similar to
converting Standard
●Because Umami is a lot more specialized
than standard, it is expected to yield
fewer building block recipes than
Standard did, and will be less
composable
●It is intended to be a self-contained
demo rather than a set of reusable parts



RECIPES in core
35

New sets of recipes
should build on 

core recipes

You can require a core recipe into a new
recipe simply by listing it in the recipes
section of recipe.yml.
RECIPES in core
… pretty much every
conceivable set of
recipes should build on
the recipes in core. Doing
so is the best and easiest
way to make sure your
recipes integrate well
with others
36

What we’re
working on


Unpacking
recipes

●Recipes might require dependencies to
be installed.
●If a recipe is removed, its dependencies
will be also removed.
●Unpacking recipes’ dependencies solves
this issue.
Applying recipes
38

Config
validation

●When applying a recipe, there was no
real promise that it would work.
●Even if a recipe don’t blow up while
being applied, it would just leave a mess.
●This is now solved with validating
validatable configuration.
●Creating config storage checkpoint
before applying a recipe.
What we’re working on
39

Making config
actions more
dynamic

When you used to create recipes and needed
to apply a certain action to multiple bundles,
you’d have to create multiple lines of the same
action to the list of bundles. Now, thanks to the
community, we are able to run more dynamic
config actions to support wildcards.
What we’re working on
40
user.role.*:
grantPermissions:
- 'access content'


core.entity_view_display.node.*.*:
removeComponent: links


field.field.media.*.field_tags:
setSettings:
auto_create: false
user.role.media_creator:
grantPermissionsPerMediaType:
- 'create %bundle media'
- 'edit own %bundle media'
- 'delete own %bundle media'


field.storage.node.field_tags:
instantiateOnAllBundles:
label: Tags
description: 'Add some tags here.

What we’re working on
41
●Building UI for applying recipes
●Hosting recipes on Drupal.org
●Recipe discovery
●Drupal recipe testing
The roadmap - phase 2 

●Recipe unpacking in Core
●Ensure that recipes cannot be applied in
parallel
●Allow for user input before applying
e.g. Google Maps API key

placeBlockInDefaultTheme,
placeBlockInAdminTheme
Config entity type: block
●Theme name determined
programmatically
●Pass an array of regions
with a fallback
●Use ‘first’ or ‘last’ keywords
for placements within
region
Anatomy of a recipe
42
Actions for
blocks

config:
actions:
block.block.powered_first_default:
placeBlockInDefaultTheme:
id: powered_first
# The region accepts an array keyed by theme name.
region:
bootstrap: footer
gesso: page_bottom
olivero: footer_top
# Fallback if no match found in the region array.
default_region: content
# Place before any blocks already in the region.
position: first
plugin: system_powered_by_block

Recipe maintainer
and end user
documentation 

●Documentation currently lives in gitlab.
●There is a lot of work to be done to get
the documentation ready for
maintainers and end users.
●This is a great way to start contributing
to recipes


What we’re working on
43
Graphic here?

Recipes
Cookbook

The Recipes Cookbook is a collection of
contributed recipes. Get ideas and share
ideas for:

●Site-starter recipes
●Functionality-specific recipes
●Recipe sets

Add your own!


What we’re working on
44

45
Live demo!


Stupendous
Date Tricks

Tomorrow at 11:00am

Mobomo Room

Expanded Demo

47
Join the
initiative


Get involved!

●Recipe maintainer and end user
documentation needed
●Developers and testers wanted
○test coverage
●Recipes wanted
●#recipes in Drupal Slack
●Join us in Slack meetings every other
Tuesday at 1600 UTC
●Join us at contrib day at DrupalCon



Join the initiative
48

49

Special 

thanks to

@alexpott, @wimleers, 

@phenaproxima, @thejimbirch

@bircher, @smustgrave, @narendraR…


Bon appétit!


Questions?
@mandclu
Stickers!