Recipes: It's About Time - Twin Cities DC 2024

mandclu 160 views 51 slides Sep 12, 2024
Slide 1
Slide 1 of 51
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

About This Presentation

Learn about Drupal recipes, how they will make your life as a website builder easier, and especially how they make it easier than ever to manage dates and times on your website.


Slide Content

Recipes:

It’s About
Time!

Sept 12, 2024

Martin
Anderson-Clutz

Senior Solutions Engineer

Starshot Track Lead,

Events Recipe

@mandclu


Agenda

Why recipes?1
Anatomy of a recipe2
Applying recipes3
What we’re working on4
Events recipes5
3
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:
5

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:
6

Anatomy of 

a recipe


config
content
composer.json


recipes
install
config:import
config:actions



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

9

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

Anatomy of a recipe
10
{
"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
applied with it.
Anatomy of a recipe
11
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
12
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
13
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
14
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
15

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
16
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
17
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
18
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
19
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
20
●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
21
●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?

22

23

Applying
recipes


How to apply a recipe

Applying recipes
25

> 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
26

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.
27
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
28

> 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]
29
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
30

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
31

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
33

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
34

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
35
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
36
●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 placement
within region
Anatomy of a recipe
37
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

Coming in Drupal 11.1

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
38
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
39

40

41
Events 

Recipes


●Event content type
○Smart Date field
○Add-to-calendar links
●View for upcoming and past events
●Working on:
○UX improvements
Events Recipes
42
Events


●Address and Geofield handling addresses
●Nominatim (OpenStreetMaps) as a free
geocoding service that work out-of-the-box
●Leaflet as a free, extensible mapping solution
●“Where” reference field on Events
Events Recipes
43
Locations, Events Locations


●Adds a Calendar view
○Currently based on Fullcalendar View
●Drag-and-drop to edit, double-click to add events
●Working on:
○Fullcalendar module as an equivalent,
community-supported module
Events Recipes
44
Add-on: Events Calendar


●Adds a Drupal-based registration system
○Based on the Entity Registration module
○Fieldable
●Working on:
○Improved registration UX
Events Recipes
45
Add-on: Events Registration


●Adjust Event configuration to allow for recurring dates
○Install Smart Date Recur
○Enable recurring for “When” field
○Change formatter to Recurring
○ Add permission to editor role
Events Recipes
46
Add-on: Events Recurring (coming soon)


47
Live demo!


48
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
49

Bon appétit!


Questions?

@mandclu

[email protected]