Moving to the Default content system.
thejimbirch → created an issue.
Thanks for the explanation, I will try to be more cognizant of that in the future.
Moving it back because the test coverage would need to go into core.
Moving to the recipes initiative project where the documentation lives.
This was a new site spinup on 11.2 for an internal demo. It's been buggy, so it could be something unrelated.
But my unusual thing here is that I only have Gin as the front end and admin theme.
Steps to replicate
drush si minimal -y
composer require drupal/gin drupal/drupal_cms_ai
drush uli
Visit /admin/appearance
Set Gin as the default theme
Set Default theme as the Administration theme
Save
drush recipe ../recipes/drupal_cms_ai
If I manually create the block and export the config, it looks like this. Most of the additional settings are the default values.
langcode: en
status: true
dependencies:
module:
- ai_chatbot
theme:
- gin
id: ai_chatbot
theme: gin
region: content
weight: 0
provider: null
plugin: ai_deepchat_block
settings:
id: ai_deepchat_block
label: 'Drupal Agent Chatbot'
label_display: visible
provider: ai_chatbot
ai_assistant: drupal_agent_assistant
bot_name: 'Drupal Agent'
bot_image: /core/misc/druplicon.png
use_username: 1
default_username: User
use_avatar: 1
default_avatar: /core/misc/favicon.ico
first_message: 'Hello! How can I assist you today?'
stream: 0
toggle_state: remember
width: 400px
height: 500px
placement: bottom-right
show_structured_results: false
show_copy_icon: true
collapse_minimal: false
style_file: 'module:ai_chatbot:bard.yml'
verbose_mode: false
visibility: { }
Is the block is created using the placeBlockInAdminTheme
config action?
block.block.ai_chatbot:
placeBlockInAdminTheme:
region:
gin: content
claro: content
default_region: content
plugin: ai_deepchat_block
settings:
id: ai_deepchat_block
label: 'Drupal Agent Chatbot'
label_display: '0'
provider: ai_chatbot
ai_assistant: drupal_agent_assistant
bot_name: 'Drupal Agent'
stream: 0
default_avatar: /core/misc/druplicon.png
first_message: 'Hello! How can I assist you today?'
show_structured_results: 1
ai_chatbot is a submodule of the ai module. It has no config entities, nor does the ai module.
thejimbirch → created an issue.
thejimbirch → created an issue.
Not if we add DrupaCon Europe 2026, and North America 2027 nodes when they are announced.
How about we set a precedent to have default content for any upcoming DrupalCons? That is assuming the event recipe is staying in Drupal CMS.
DrupalCon Vienna 2025
14 October 2025 - 17 October 2025
DrupalCon Chicago 2026
23 March 2026 - 26 March 2026
DrupalCon Nara 2025
17 - 19 November 2025
benjifisher → credited thejimbirch → .
thejimbirch → created an issue.
I am terrible at CSS today, and need to have this looking ok for a demo, so I made MR-2 that has a badge styling in the bottom right.
Also uploading patch of the MR
thejimbirch → created an issue.
Thanks for fixing my copy pasta error!
Simple config files are always imported.
Good to know. I just updated it to only import the two menus.
I don't believe so. The commit contains an update hook that adds the menu if the user does not have it.
https://git.drupalcode.org/project/drupal/-/commit/f77a485d9141dcaf9c7bd...
/**
* Creates the Navigation user links menu.
*/
function navigation_post_update_navigation_user_links_menu(array &$sandbox): void {
$menu_storage = \Drupal::entityTypeManager()->getStorage('menu');
// Do not create the new menu if already exists.
if ($menu_storage->load('navigation-user-links')) {
return;
}
$menu_storage
->create([
'id' => 'navigation-user-links',
'label' => 'Navigation user links',
'description' => 'User links to be used in Navigation',
'dependencies' => [
'enforced' => [
'module' => [
'navigation',
],
],
],
'locked' => TRUE,
])->save();
}
MR added that imports all the config from the Navigation module. Since the Navigation module is under active development, and Christina is the UX lead for both the module and Drupal CMS, I think it is safe to assume that any config entities they add are meant for Drupal CMS also.
If I am wrong about this, we can list the two menu configs individually.
thejimbirch → created an issue.
I believe I addressed the points in the MR
thejimbirch → made their first commit to this issue’s fork.
thejimbirch → created an issue.
thejimbirch → created an issue.
Yes, I believe this functionality is still wanted.
thejimbirch → created an issue.
thejimbirch → created an issue.
Thanks for working on this.
This is a good start, but I would like to have the content from the blog post to be put at the top level page here:
https://project.pages.drupalcode.org/distributions_recipes/default_conte...
And then in the author guide where you worked, add a link to the top level default content page.
# Default Content in Recipes
In Drupal 10.3, the DefaultContent API was added to Drupal core as part of the experimental Recipes APIs. These APIs allow Drupal to create content from files that are part of a recipe.
This content that we programmatically create isn’t intended for deploying or migrating content, we have the Workspaces and other modules for that.
Instead, it can be a great tool in our toolkit for creating demos and test content, while freeing developers and testers from the drudgery of repetitive content creation.
## The Default Content contrib module
While we added a way in core to consume content config files from recipes, we are still at the start of what core can do, and mid-journey of what the contrib module aims to do.
Until the recent interest from the Recipes Initiative team, the Default Content module has always been used for creating default content configuration files for custom modules and install profiles. You could create content on a local site, export it to your module or a module in an install profile, and when that module was enabled (or a site was started from the install profile), and you installed the default content module as a dependency, you would get your content imported. This all still works exactly as it always has, and now it can also be used with recipes.
## Using the Default Content module
The export process is the same for modules and recipes. Let’s review that now.
## Getting set up
Install the module as you normally would. Since I am using the module for creating content for recipes, I install it in the dev section of my composer requirements as I do not need it in production.
```bash
composer require --dev drupal/default_content
```
And enable the module:
```bash
drush en -y default_content
```
The module doesn’t have a user interface. Instead, it provides Drush commands that can be run to export content.
## What can we export?
Out of the box, we can export the following entity types:
- **Content type nodes**: `node <node id>`
- **Taxonomy Terms**: `taxonomy_term <taxonomy term id>`
- **Files**: `file <file id>`
- **Media**: `media <media id>`
- **Menu Links**: `menu_link_content <menu link id>`
- **Content blocks**: `block_content <block id>`
- **Shortcuts**: `shortcut <shortcut id>`
At this time, there isn’t a way to export by bundle type (e.g., all nodes of type Article, or all menu links from the main menu), but there is a patch for it.
Let’s take a look at the three commands that the module provides to export content.
## Default content Drush commands
### `default-content-export-references`
Exports an entity and all its referenced entities. This is my go-to command as it helps you export referenced media, files, taxonomy terms, and users from the parent node.
**Alias**:
`dcer`
**Arguments**:
- `entity_type` – The entity type to export.
- `entity_id` – The ID of the entity to export.
*One of these arguments is required.*
**Options**:
- `folder` – The module or recipe’s content folder to export to. Entities are automatically grouped by entity type into directories.
**Examples**:
```bash
# Exports node 123 and all its dependencies.
# To a module:
drush dcer node 123 module_name
# To a recipe:
drush dcer node 123 --folder=recipes/recipe_name/content
# Export all nodes and all their dependencies.
drush dcer node --folder=modules/custom/my_custom_module/content
```
---
### `default-content-export`
Exports a single entity. Use this if you want to manage your own dependencies.
**Alias**:
`dce`
**Arguments**:
- `entity_type` – The entity type to export.
- `entity_id` – The ID of the entity to export.
*Both arguments are required.*
**Options**:
- `file` – Write out the exported content to a file instead of stdout.
**Example**:
```bash
# Exports node 123 only. You are responsible to export dependencies.
drush dce node 123 module_name
```
---
### `default-content-export-module`
Exports all the content defined in a module info file. This is most helpful for distribution and install profile maintainers who want to maintain and update default content from a canonical source.
**Alias**:
`dcem`
**Arguments**:
- `module` – The machine name of the module (required).
**Options**:
None
**Example**:
```bash
# Exports all the content defined in a module info file.
drush dcem module_name
```
The module's info file would need to have a section like this:
```yaml
default_content:
node:
- c9a89616-7057-4971-8337-555e425ed782
- b6d6d9fd-4f28-4918-b100-ffcfb15c9374
file:
- 59674274-f1f5-4d6a-be00-fecedfde6534
- 0fab901d-36ba-4bfd-9b00-d6617ffc2f1f
media:
- ee63912a-6276-4081-93af-63ca66285594
- bcb3c719-e266-45c1-8b90-8f630f86dcc7
menu_link_content:
- 9fbb684c-156d-49d6-b24b-755501b434e6
- 19f38567-4051-4682-bf00-a4f19de48a01
block_content:
- af171e09-fcb2-4d93-a94d-77dc61aab213
- a608987c-1b74-442b-b900-a54f40cda661
```
---
# Creating a Drupal recipe with Default content
So let’s create a recipe that can store default content we can send to a test server so our QA engineer can test. We’ve created a node that has our new feature on our local environment. Rather than having to rebuild that page manually, we will export the content and apply the recipe after it has been deployed.
## Create the recipe structure
We keep our recipes in the recommended folder above the webroot.
You can manually create a recipe folder, the content folder, and a `recipe.yml` file or use the command line:
```bash
mkdir recipes/recipe-name
mkdir recipes/recipe-name/content
touch recipes/recipe-name/recipe.yml
```
In our `recipe.yml` file, we only need a name, description, and type:
```yaml
name: 'Recipe name'
description: 'Demo content for ticket xyz'
type: 'Content'
```
## Export your content
Use the Drush commands above, usually `dcer`, to export the content you need. Verify in your `/content` folder that you now have the entities you expect. It should look something like this:
(Directory structure omitted for brevity)
## Uninstall the module
We can now uninstall the Default Content module from our local environment.
Normally, we just use recipes in our local development environments and deploy the resulting config. But when leveraging the Default Content module in your recipes, you will deploy them to your server.
Once deployed and applied on your site, you’ll probably want to remove your recipe in a subsequent pull request as you don’t need it in production.
Commit and deploy your new recipe along with your code changes as you normally would.
thejimbirch → created an issue.
thejimbirch → created an issue.
thejimbirch → created an issue.
Thank you all!
thejimbirch → made their first commit to this issue’s fork.
I just used the patch myself and it allowed the recipe to be applied.
Adding a patch of MR-191 for use in composer.
Merge request added. Moving to needs review.
thejimbirch → created an issue.
This change record has details on the config action you would use to add it.
Should this be closed now that https://www.drupal.org/node/3519491 → landed?
thejimbirch → created an issue.
Gin has not released a 5.x branch yet.
Thanks so much! I will revisit this with my client.
I noticed you added credit in the commit message, but that didn't carry through to the issue itself.
Could you update?
Thank you so much!
After some discussion with @pameeela in Slack, I think nodes are actually a fine fit for these, in combination with www.drupal.org/project/entity_display_route, which is slated to be merged into core but hasn't quite made it over the finish line for 11.2.
entity_display_route doesn't have a full release, nor is it covered by the security team. Do we need to break out an issue for that? Looks like the core issue, ✨ Support adding additional routes for view modes other than 'full' Active is blocked by a path and pathauto issue.
Agreed.
We have a core Sue for this also
https://www.drupal.org/project/drupal/issues/3446561 ✨ Automatic recipe generation from config diff Active
And some folks in contrib have created a sandbox module
I understand, but developers can take product owners words literally, so thank you for the clarification.
To follow up, there are patches that are RTBC for this waiting to be ported back to 11.1, 10.5, and 10.4. Hopefully we can get those landed soon.
Could you try on Drupal 11.2? I believe it could be fixed by this:
You don’t install recipes.
you also don’t need to have the installer type if you have th latest version of composer installers. Moving to needs work.
Can we not actually ship the site template recipes with Drupal CMS, and instead require them on application?
Leaving recipes in the code base of an existing site leads to dependency locking and can block site owners from updating.
We have already seen this on Drupal CMS 1.0, where users will have to update the SEO Tools recipe in order to update the field_group module from v3 to v4. Recipes were designed to be ephemeral and not stick with the site they have been applied to for these dpendency issues.
Now that recipes are unpacked in Drupal CMS 2.0, and project browser can be used to list projects from APIs, we should be able to fulfill the requirement to offer three site templates to Drupal CMS, but not actually "ship" them in the code base.
Thanks for the RTBC @smustgrave. It’d be great to see this backported.
Patch added from the diff of the MR.
Merge request added that makes Equal the default, selected choice and moved Advanced to the end.
This way, a user does not have to make make any changes on the layout screen and the grid will render as expected.
thejimbirch → created an issue.
Added Needs change record tag.
They are downloaded into the vendor folder because the project needs to be set up correctly. Drupal core’s recommended template should be linked as a guide.
if you use drush to apply a recipe, you donated to cd into the web root. Drush always runs there. If you use the Drupal php script, you do need to cd into the web root.
I’m not sure we want to maintain a page here when we already have the project documentation
Added the link back, and links to the recommended link.
Adding credit for discussions in slack.
Adding Needs change record tag.
thejimbirch → created an issue.
Created a follow up issue in the Recipes component of core.
thejimbirch → created an issue.
In my recipes, I remove the
field_
and replace it with sa_
(for saplings). There is a secret simple config called field_ui.settings where you can change it.
I call it secret because it has no UI, you need to change it in the config and then import it.
This is expected. The event recipe treats the field_date strictly. Meaning if there is a field_date in the system, then it HAS to look exactly the same as it does in the recipe, and if it doesn't, it should fail.
Here is where that is in the recipe.
https://git.drupalcode.org/project/drupal_cms/-/blob/1.x/recipes/drupal_...
Updated issue summary
thejimbirch → created an issue.
system.site
is a simple config file, not a config entity. For those you can use the simpleConfigUpdate
config action.
name: Test Recipe
description: A recipe to change the site name.
type: Site
actions:
system.site:
simpleConfigUpdate:
name: "Ipsum Lorem"
The code in this merge request looks fine, but I think the ideal situation would be to also remove the recipes from the code base.
Like project browser can list and install projects from Drupal.org's JSON API, I feel like we should also have a browser that would list the approved Drupal CMS recipes from Drupal.org. When a user chooses to apply a recipe, the recipe is downloaded, applied, unpacked, and removed in one step.
That way, the recipe is truly ephemeral, and the user gets the latest version when they choose to browse and apply.
Great approach. Re-running tests as the failures seem unrelated.
Moving to RTBC assuming the tests pass.
thejimbirch → made their first commit to this issue’s fork.
Added some MR comments.
thejimbirch → created an issue.
thejimbirch → created an issue.
Adding the correct tag, MidCamp 2025
.
Adding the correct tag, MidCamp 2025
.
Adding the correct tag, MidCamp 2025
.