Skip to main content

Recipe Code Installer: Bridging the gap between configuration and functionality

Chief Technology Officer
May 26, 2025

Recipe Code Installer represents an innovative bridge between Drupal's established custom module paradigm and the newer Recipes concept. While custom modules have been a cornerstone of Drupal development for many years, allowing developers to extend Drupal's functionality with PHP code, Recipes emerged as a more configuration-focused declarative approach to site building. 

Recipe Code Installer merges these concepts by allowing Recipes to bundle a custom module that becomes part of a Drupal project's codebase.

Understanding Drupal Recipes and their limitations

Drupal Recipes were introduced as a powerful way to automate module installation and configuration. They provide pre-packaged, shareable solutions that bundle years of expertise into reusable components. By design, Recipes have specific limitations to keep them functional and sustainable:

  • They cannot have their own code (when custom functionality is needed, the required code must be packaged as a Drupal module, downloaded via Composer, and then installed by the Recipe)
  • They cannot make dynamic changes
  • They cannot provide their own upgrade path

These constraints ensure that Recipes remain ephemeral - once applied, the results become the project’s responsibility. While this approach works well for configuration-based functionality, it creates challenges when necessary changes and functionalities can only be achieved via custom code.

How Recipe Code Installer works

Recipe Code Installer solves this limitation by running as the final stage of recipe installation. The process works as follows:

  1. When a Recipe is applied, Recipe Code Installer checks for the presence of a code subdirectory within the Recipe.
  2. If custom module code is detected, it extracts this code and moves it to your project's custom module directory.
  3. It then installs the module by calling Drupal's module install function.

This approach maintains the ephemeral nature of Recipes while allowing them to deliver custom functionality through proper module installation. Unlike traditional Recipes which are applied and then "forgotten", Recipe Code Installer creates a new custom module on the project where it was applied, effectively transforming configuration-only Recipes into a vehicle for delivering both configuration and custom code.

The directory structure for a Recipe using this functionality looks like:

enhanced_event_recipe/
├── code/                   # Custom module code to be installed
│   ├── enhanced_event_recipe.info.yml
│   ├── enhanced_event_recipe.module
│   ├── enhanced_event_recipe.services.yml
│   └── src/
│       ├── PricingCalculator.php
│       └── Plugin/
│           └── Validation/
│               └── EventCapacityConstraint.php
│       └── ...
├── config/                      # Standard Recipe configuration
│   ├── node.type.event.yml
│   └── ...
└── recipe.yml                      # Standard Recipe definition

Problem: Managing supporting code for Recipes

 

Challenge for Recipe creators

Creating and maintaining custom functionality for Recipes traditionally requires managing multiple packages:

  • Developing a separate custom module
  • Hosting it somewhere (Drupal Packagist, Packagist, private repository)
  • Creating a Recipe that installs this module
  • Maintaining both packages separately

This dual-package approach increases overhead and complicates the development workflow.

Challenge for Recipe adopters

When Recipes install external module dependencies via Composer, projects become dependent on third-party maintainers. This dependency can:

Solution: Recipe Code Installer

 

For Recipe creators

  • Streamlined development process: Package everything in a single Recipe.
  • Simplified maintenance: Update code and configuration together.
  • Flexible evolution: Code bundled inside a Recipe can evolve with the Recipe without semantic versioning constraints.
  • Focused functionality: Deliver precisely what's needed without creating a full-fledged module.

For Recipe adopters

  • Code ownership: Bundled code becomes project code owned by the project maintainer.
  • Reduced dependencies: Eliminate external dependencies that could block upgrades.
  • Complete control: Modify the bundled module according to project-specific needs.
  • Seamless integration: Custom code is installed as a standard Drupal module.

Practical use cases

This approach is particularly valuable for:

  1. Project-specific customizations that don't require a full module.
  2. Reusable components developed by agencies or product teams that need consistent deployment across multiple projects.
  3. Integration bridges that require small amounts of custom code.
  4. Complex content features that need custom entity handlers, entity hook implementations or access logic.

Implementation considerations

When using Recipe Code Installer, keep these best practices in mind:

  1. Keep bundled code focused - Only include code that's necessary for the specific functionality.
  2. Follow Drupal coding standards - Ensure your bundled code follows Drupal's best practices.
  3. Consider documentation - Include clear documentation about the bundled code's functionality.
  4. Test thoroughly - Test both the Recipe application and the bundled module functionality.

Conclusion

Recipe Code Installer represents a thoughtful extension to Drupal Recipes that addresses a practical limitation while maintaining the core philosophy that makes Recipes valuable. By allowing Recipes to bundle custom module code that gets properly installed in the project's codebase, it bridges the gap between configuration-based and code-based functionality, making Recipes even more powerful and flexible for Drupal developers.

For Recipe creators, this approach simplifies the development process by eliminating the need to maintain separate packages and allowing bundled code to evolve freely without semantic versioning constraints. For Recipe adopters, it provides full ownership of the custom code, eliminating the risk of being blocked by external dependencies during major version upgrades or other significant changes.

This dual benefit ensures that both Recipe creators and adopters can work more efficiently: creators can focus on crafting the best possible solutions without the overhead of managing multiple packages, while adopters gain complete control over all aspects of their codebase, allowing their projects to evolve at their own pace.

carrot in a book

We invite you to try Recipe Code Installer and share your feedback! Join the conversation on Drupal.org, contribute to the project's issue queue, or share your ideas on how to further improve its functionality.



All Pronovix publications are the fruit of a team effort, enabled by the research and collective knowledge of the entire Pronovix team. Our ideas and experiences are greatly shaped by our clients and the communities we participate in.
 

 

Dezső is the Chief Technology Officer at Pronovix. He wanted to have a computer from a very young age — not for playing games, but to do programming and other cool stuff. He started learning web programming at high school where he met his mentor László Csécsy (boobaa) who introduced him to Drupal. He earned a BSc degree in Bachelor of Business Information Technology and later an MSc degree in Software Engineering at the University of Szeged in Hungary. Thanks to his enthusiasm for computers and programming he is always ready to improve his skills, and can quickly learn new languages and technologies.

Newsletter

Articles on devportals, DX and API docs, event recaps, webinars, and more. Sign up to be up to date with the latest trends and best practices.

 

Subscribe