That is a good idea since it is a really good example of recipe input.
I'll set it up. If anyone wants to be a maintainer, let me know.
This is looking great. Left some small comments. I will add a change record now.
thejimbirch → changed the visibility of the branch 3555022-document-default-content to hidden.
Suggestion from the previous issue implemented. It makes it a lot easier to read. Tests pass. Marking as RTBC
Everything is green, Change record updated, even better tests, and all of entity type!
Marking as RTBC.
Go team Default Content!
Typo fix. Thanks for the great documentation.
thejimbirch → made their first commit to this issue’s fork.
Another:
https://drupal.slack.com/archives/C2THUBAVA/p1724874830469789?thread_ts=...
To add and configure new fields in field groups.
Create the field storage configs and put them in the /config folder. These will be idempotent because nothing can ever change on them (I'm pretty sure that is true).
Use addToAllBundles to create the field instances on every type (what would you do if you only wanted it on one or 2 bundle types?)
field.storage.node.field_seo_analysis:
addToAllBundles:
label: 'SEO Analysis'
description: 'Pick the main keyword or phrase this page is about.'3. Use setThirdPartySettings to create the field_groups
# Configure field group.
setThirdPartySettings:
- module: field_group
key: group_administration
value:
children:
- group_content
- group_seo
label: Administration
region: content
parent_name: ''
weight: 1
format_type: tabs
format_settings:
classes: ''
show_empty_fields: false
id: 'group_administration'
label_as_html: false
direction: horizontal
width_breakpoint: 640
- module: field_group
key: group_content
value:
children:
- body
- field_image
- field_tags
- field_when
- field_where
- field_location_address
- field_location_telephone
label: Content
region: content
parent_name: group_administration
weight: 20
format_type: tab
format_settings:
classes: ''
show_empty_fields: false
id: 'group_content'
label_as_html: false
formatter: open
description: ''
required_fields: falseNOTE: Tabs may not be the best thing to do as once you do tabs, all the fields should be in the tabs or it looks funny. But the good news is you can have a bunch of field names in the children section and it doesn't break it if a bundle doesn't have that field.4. Use setComponent(s) to add the fields in the form and display
setComponents:
-
name: field_seo_analysis
options:
type: yoast_seo_widget
weight: 18
region: content
settings:
render_theme: olivero
render_view_mode: default
edit_title: 0
edit_description: 0
third_party_settings: { }
-
name: field_seo_description
options:
type: string_textarea
weight: 16
region: content
settings:
rows: 5
placeholder: ''
third_party_settings: { }The composer plug-in was added to core in 11, but it can be manually added to 10.x sites.
Hi folks,
I don't think the change was ever committed, but unlike modules, there are no subfolders in recipes config folder. Config files are either treated strict (Recipe will fail if it exists and is different), or lenient (Recipe will skip the config if it exists).
We recommend treating field.storage, entity.type configs strictly as they sculpt the database. But in real life, there are some configs that do more like layout_builder__layout and media field configs that are often changed on sites.
So right now, if that config exists on a site, your customizations are not applied. I don't use Layout Builder, but is this needed to make your recipe work?
persist_with_no_fields: node.type.landing_page.yml
core.entity_view_display.node.landing_page.default.yml
field.field.node.landing_page.layout_builder__layout.yml
field.storage.node.layout_builder__layout.yml
You shouldn't need to do anything. The plugin is added at the project level, and unpacks this recipe's dependencies to that project's composer.json.
The Contact module is being removed from core in 📌 [meta] Tasks to deprecate the Contact module Active .
In 📌 Remove Contact module recipe from core Active we are running into issues with tests that use the contact module. Do the same issues appear here?
thejimbirch → created an issue.
Deleted the recipe and removed it from being applied from the standard recipe. Lets see what happens to the tests.
thejimbirch → made their first commit to this issue’s fork.
Its a simple change in the composer file. You could edit your local file to match https://git.drupalcode.org/project/ai_recipe_seo_optimizer/-/merge_reque...
I added an LLM generated script, and a DDEV command to run the script (not sure if that is needed/wanted).
I stink at PHP, so feel free for anyone to take over and make this better.
Updated both 2.x and 1.2 branches with requested changes. Resolved all threads.
Updated the prompt
1. Removed extra line breaks deviating from Drupal README recommendations.
2. Added Bugs and feedback section
3. Added (core) to all core projects
4. Changed composer command from one to three backticks (```)
5. Linked "Drupal CMS" (in the Installation section) to https://drupal.org/project/cms
6. Removed MODULES.md and the DDEV command that generated it
7. Updated the prompt to handle Drupal CMS Helper and any future modules if directed,a nf added a README for it.
I gotta say, this is also a pretty damn decent use of AI, although how will we be able to regenerate it without a Claude Code subscription? :)
Any LLM with access to the code base (Claude Code, Gemini CLI, Cursor, etc) should be able to use this prompt and get the same results.
For LLMs that don't, you can use a tool like https://gitingest.com/ to flatten the code to a flat file and feed that with the prompt.
The results from chatGPT were the same.
resolved all threads and added an updated prompt to the code base.
Ready for review.
I created a one shot prompt to create the READMEs that could be used again in the future to update them.
Create README.md files for each recipe folder in /recipes based on their recipe.yml files. Each README should follow this format:
# Drupal CMS [Recipe Name from recipe.yml]
[Description from recipe.yml]
## Recipes applied
- [List each recipe from the recipes: section]
## Modules and themes installed
- [List each module/theme from the install: section]
## Configuration changes
- [List only the configuration keys from config:actions section]
## Installation
This project is part of Drupal CMS. If you're not using Drupal CMS, you can
still use this recipe in your own project. Add it with the following Composer
command:
`composer require drupal/[recipe_folder_name]`
## Contribution
All bug reports and feedback should be filed in the
[Drupal CMS issue queue](https://www.drupal.org/project/issues/drupal_cms).
---
Follow Drupal README guidelines: capitalize headings with initial capitals, use # for h1 (recipe name only), ## for h2, wrap text around 80 columns, use dashes for bulleted lists, and use meaningful link text.
Omit sections that have no content (e.g., if no recipes are applied, omit that section entirely).
This prompt contains all the formatting requirements and structure needed to regenerate these README files.
Since the other recipe requires a Drupal CMS recipe like this:
"drupal/drupal_cms_content_type_base": "^1.2 || ^2.0",
And 1.2 is stable, you got that. While this recipe is just ^2 and that requires the latest version of ECA.
I will try to see if this recipe works on 1.2
That makes it much more obvious. Moving to RTBC, thanks!
It is super subtle for this to only have a question mark on the end. Are there any other patterns/options that would make this more obvious to recipe authors?
If not, I will recommend always including a comment when this is used in the documentation.
It would be good to also document some use cases for the change record.
Discussed this aloud and agreed on an approach and testing. I look forward to seeing this progress.
thejimbirch → created an issue.
thejimbirch → created an issue.
Fixed merge conflict manually, updated some comments.
We still need one patch.
"patches": {
"drupal/core": {
"TypeError in CreateForEachBundle when processing config with integer or boolean schema types": "https://git.drupalcode.org/project/drupal/-/merge_requests/13406.patch"
}
}Or via the CLI:
composer config extra.patches."drupal/core"."TypeError in CreateForEachBundle when processing config with integer or boolean schema types" "https://git.drupalcode.org/project/drupal/-/merge_requests/13406.patch"
Since this is a bug in the existing code base, would it be possible to bring this down to 10.x also?
We're needing this in the AI initiative SEO Optimizer recipe → .
Updates links and adds details for contributing.
This looks good to me. Love the example in the comments of the action. Marking RTBC.
Validated this works by using it on ✨ SEO Content suggestions Active
Calling all testers! That is beyond my skillset.
I have validated this works in ✨ SEO Content suggestions Active
I have this working for node title, SEO Title, and SEO Description.
Unfortunately, I found a lot of bugs, but fortunately, there are now patches!
"patches": {
"drupal/ai": {
"Make setup field widget action config action support bundle wildcards": "https://git.drupalcode.org/project/ai/-/merge_requests/930.patch",
"AI Automator status field fails on config import": "https://git.drupalcode.org/project/ai/-/merge_requests/932.patch"
},
"drupal/core": {
"TypeError in CreateForEachBundle when processing config with integer or boolean schema types": "https://git.drupalcode.org/project/drupal/-/merge_requests/13406.patch"
}
}thejimbirch → created an issue.
I had to reroll the patch to get it to apply. Created a merge request for it, and asked Claude to summarize the changes.
This refactors the config import state tracking to prevent status field modifications during configuration synchronization.
Key Changes:
1. Replaces import toggle function with state checks (lines 41-47, 57-63, 73-79):
- Removes dependency on ai_automators_can_import_toggle() function
- Adds explicit checks for ai_automators.importing state and config.installer syncing status
- Modifies conditions in ai_automators_entity_insert(), ai_automators_entity_update(), and ai_automators_entity_delete() hooks
2. Updates import state management (lines 99-120):
- Renames ai_automators_config_import_steps_alter() hook implementation (previously had incorrect docblock)
- Sets ai_automators.importing state flag to TRUE at import start
- Adds cleanup callback _ai_automators_cleanup_import_state() to batch process
- New cleanup function deletes the import state flag when import completes
Technical Impact:
- Prevents status field modifications when importing config or during config sync operations
- More reliable state management using Drupal's state API instead of toggle function
- Ensures proper cleanup of temporary state after import completes
thejimbirch → made their first commit to this issue’s fork.
thejimbirch → changed the visibility of the branch hotfix/wip to hidden.
thejimbirch → created an issue.
The AI module has a lot of frameworks that does not actually do anything by themselves, but needs to be setup to work correctly. The AI Automators, AI Search, Field Widgets and AI Agents are all useless without actual setups.
Since AI can solve very specific business cases, its very hard to ship the AI module one-size-fits-all solutions and that's where recipes comes in.
However to be able to utilize recipes correctly we have added some config actions that you can use to setup recipes.
### verifySetupAi
In many cases a recipe doesn't really care if its Gemini or OpenAI behind the scenes, it might just care about what is the capabilities of the model that is setup.
Or we might have 20 recipes that sets up one AI button or AI Agent each and we do not want all of those to be inheriting from a AI Provider setup recipe, when the site might already have a AI provider setup.
This action helps with that - its not actually an action though, its a workaround that check if all the dependencies on the system are met, and if not it will throw an exception so the recipe reverts any changes.
There are 4 things you can verify (and you can mix)
#### provider_is_setup
This takes an array of the providers you want to check for and if they are actually setup and working (API key set, host set etc.).
Example where I want to verify if OpenAI exists and is setup:
```
config:
actions:
ai.settings:
verifySetupAi:
provider_is_setup:
- openai
```
#### operation_type_has_provider
This takes an array of the possible operation types and checks if there exists one provider at least that handles this.
Example where I want to verify if a chat and an image generation model exists:
```
config:
actions:
ai.settings:
verifySetupAi:
operation_type_has_provider:
- chat
- text_to_image
```
#### operation_type_has_default_model
This takes an array of the possible operation types and checks if a default model exists for this.
Example where I want to verify if a chat default model exists:
```
config:
actions:
ai.settings:
verifySetupAi:
operation_type_has_default_model:
- chat
```
#### vdb_provider_is_setup
This does the same as the provider, but checks if a vdb provider is setup.
Example where I want to check if Milvus is setup:
```
config:
actions:
ai.settings:
verifySetupAi:
vdb_provider_is_setup:
- milvus
```
Based on your MR, the Key module does not provide any config actions. The create action comes from core, as does recipe input.
I like the idea of documenting how to add create a key in a recipe, but since the Key module is not creating any actions, this is not the place.
I do have ✨ Add a Recipe Examples section to the docs Active as a placeholder to add a new section to the docs that creates recipe.yml snippets on how to do common tasks. I think your documentation should go there.
Also, for reference, the createIfNotExists config action may be better to use rather than the create action so if the key exists, then the recipe won't fail.
We are moving this part to post-MVP:
Provide a view with all content types and SEO scores similar to the content overview page. Provide a batch operation to analyse multiple pages at once.
Use the custom_field module to add these fields so we can send a single prompt to populate both fields.
We want to use the config actions to validate if the operations we need rather than require Drupal CMS AI recipe.
Moving to needs work.
This could be action-ed.
We are most likely going to be blocked by ✨ Config action to set a third party setting of a display (form or view) component Active
Moving back to Needs work as there is a merge conflict.
This is looking great. I updated the title and a bit of the description.
Moving back to Needs work as there is a merge conflict on the test.
The contrib PWA module is still in beta and only has 2500 installs. I am a fan of the module, but since it was moved to the Drupal CMS issue queue, this issue summary would need to be overhauled for inclusion here.
Would there be a possibility of creating a recipe that would install and configure the module to make it easier for folks in contrib? I feel like that would be a good next step.
Tests are failing. Moving back to Needs work.
Can you include a link to the design?
Great work @ajinkya45! +1 for RTBC
@mlncn I maintain documentation at:
https://project.pages.drupalcode.org/distributions_recipes/recipe_author...
I added an issue to make it clearer on where to find recipes.
📌 Document where to find recipes Active
@nicxvan The distributions_recipes project was a fork of Drupal core. After we got recipes into core, the issues from that project were moved to core. There are a bunch that will need to be re-recreated against core if they are to move forward.
thejimbirch → created an issue.
The Default Content API was added to core as part of the recipes initiative, so that was our priority.
I see no reason that it cannot be extended to import content from modules also as the contrib default_content module does.
In Drupal 11.3, we now have a content exporter!
`content:export` command added to help with recipe development
https://www.drupal.org/node/3533854 →
Thanks to all who helped move this along.
Adding an non-working issue in the contrib module for reference.
Moving the default content system.
With the default_content contrib module, we could export the following types.
node
taxonomy_term
file
media
menu_link_content
block_content
shortcut
I believe all except for file could have a bundle type and would be beneficial for recipe creators.
Back to needs work for additional test coverage requested.
thejimbirch → created an issue.
I can't reproduce this and no one else has reported anything similar.
thejimbirch → made their first commit to this issue’s fork.
Thanks for the contribution!
All of @larowlan's feedback from yesterday was addressed. Moving back to RTBC for another review.
thejimbirch → created an issue.
That is a valid concern, but one that every project on Drupal.org has to endure. I am looking for a more site builder/marketer friendly way of communicating the functionality of the recipes, and linking to a text file, while it would technically help, it does seem developer-y.
If you wanted to automate the process, would we want to make another script that parses each recipe for name, description, modules, etc and saves that to a README file in each recipe. Then that can be used in the project page desc.
All threads resolved, nits picked, and rebased. Moving back to RTBC.
thejimbirch → created an issue.
Project created at https://www.drupal.org/project/ai_recipe_image_alt_text →
thejimbirch → created an issue.
Work will happen in https://www.drupal.org/project/ai_recipe_seo_optimizer →
Currently blocked by: ✨ Config action to set a third party setting of a display (form or view) component Active
A lot of the recipes folks are looking to build out for DrupalCon Vienna could use this so it would be great if it could be backported to 11.2 also.
What if a site template wants to include an admin theme, or multiple themes (domain access, multisite, etc)?
I'm not sure the development workflow would be fairly easy. Now I have to have a place to work on the theme, and then zip it up, or create a deployment mechanism to do package things up instead of a normal git composer workflow.