In this tutorial we're going to look at one the first files you will need in order to create a Drupal module: the info file. Each module is required to have a MODULE.info.yml file to help Drupal identify that a bundle of code is a unique module. This specially-formatted YAML file not only tells Drupal about the module, but also allows us to provide other useful metadata. In this tutorial, we'll walk through all of the metadata possibilities that can be included in an info file.
Create an info file in YAML format with all of the required metadata for a custom Drupal module.
- It helps to know what YAML is, but we'll provide example code that you can copy and paste. See also Introduction to YAML
- You should understand the concept of a module in Drupal. See Concept: Modules (Drupal User Guide)
- You should have a directory created for your custom module in modules/custom/MODULE where MODULE is the machine name of your module. See also Naming and placing your module (Drupal.org).
Note: It's best practice to create custom and contrib directories in your modules directory. And to place your custom modules in modules/custom. If these folders exist, Drush will place scaffolded custom modules in modules/custom and Composer will place contributed modules from Drupal.org in modules/contrib automatically.
Example (truncated) directory structure of a Drupal project
├── composer.json ├── web │ ├── index.php │ ├── modules │ │ └── contrib │ │ └── custom
Quickstart using Drush
If you have Drush installed for your project (
composer require drush/drush), you can use Drush's code generation tool to quickly create a custom module.
drush generate module
Set up a new module with an info file
Name your custom module
When choosing a machine name for your module, it must:
- Start with a letter
- Only contain lowercase letters
- Not contain spaces (use underscores (not hyphens) in place of a space)
- Be less than 50 characters
- Be a unique name within the system (no other installed module, theme, distribution, or profile can share the same name)
- Not be any of these reserved words: src, lib, vendor, assets, css, files, images, js, misc, templates, includes, fixtures, Drupal.
Create a directory for your custom module
From the root of your Drupal installation (not necessarily the project root), create a directory within /modules/custom. The custom subdirectory is optional but best practice to make it easier for you to distinguish between community-contributed and custom modules. Depending on your use case (i.e. multisite), you may also create your module directory in sites/*/modules. The modules directories in core and profiles are reserved for the core software, installation profiles, or distributions.
See Naming and placing your Drupal module (Drupal.org) for more information.
Create a new module with scaffolding
Next time you set up a module, try using the command line tool, Drush, which has code scaffolding tools built-in.
drush generate module
Learn more about Drush's code scaffolding tools in Develop Drupal Modules Faster with Drush Code Generators.
Contents: Info file reference
- Required keys in an info file
- Optional keys in an info file
- Basic example of an info file
- Declaring a dependency on 1 or more modules
- Point to settings form route with configure key
Required keys in an info file
Every info file must contain certain keys in order for Drupal to be able to actually install the accompanying module. The required keys are:
name: A name for your module.
type: The type of package. For a module info file, specify
core_version_requirement: The semantic version(s) of core compatible with your module
core(only required for core 8.7.7 and earlier): The version of core the module works with (replaced by
core_version_requirement). Read more about this change.
Optional keys in an info file
It can be helpful to provide the following optional keys in your module:
description: A brief description of its functionality (appears in the module listing on the Extend administrative page)
package: Lists the module in a group with value specified. For example, use
Customto group all your custom modules in a group named "Custom" on the Extend page.
dependencies: If applicable, provide a list of dependencies required by the module
lifecycle: Specify the stability and maintenance status of your module (see below for example values)
configure: Specify the name of the route to the module's configuration form (a link labeled "Configure" will appear in the module listing on the Extend page if a valid route is provided here)
hidden: (true) Use if you want to hide your module from the list on Extend. Used most often for modules containing automated tests. To override this setting (and list all hidden modules), add
$settings['extension_discovery_scan_tests'] = TRUEto your site's settings.php.
Read on for further examples and explanations for these keys.
Restricted keys added by Drupal's packaging system
The following keys are added by Drupal's packaging system when
"preferred-install": "dist" is specified in the project's composer.json. Don't add these manually to your module.
version: The version of Drupal, often the global constant
project: The project shortname, if the module is part of a project hosted in Drupal.org. Used in automated testing, but otherwise ignore by Drupal core.
Basic example of an info file
These are the basics you need in place in order to see your module available on Drupal's installation screen. For a module called hello_world, here are the contents of hello_world/hello_world.info.yml:
Drupal module info file
name: Hello World description: A silly example module type: module core_version_requirement: ^8 || ^9 || ^10
corekey is only needed for modules that need to run on sites running Drupal versions less than
core_version_requirementkey was introduced in 8.7.7.
- When using the
core_version_requirementkey with anything other than
core_version_requirement: ^8 || ^9 || ^10, the module should only be tested on Drupal 8.7.7 or later.
corekey cannot have a value of
10.x. Use the
- For the value of
core_version_requirement, to use a more granular version requirement than
^8 || ^9 || ^10, remove the
corekey, and specify a semantic version of the Drupal version(s) your module requires with
core_version_requirementonly. (Module will not install otherwise.)
Module is compatible with 8.7.7 and above, to the latest minor or patch version of Drupal 8; or, any minor or patch version of Drupal 9 or Drupal 10:
name: Hello World Special description: A special silly example module type: module core_version_requirement: ^8.7.7 || ^9 || ^10
Module is compatible with any minor or patch version in Drupal 9, starting with 9.4 and above:
name: Hello World Special description: A special silly example module type: module core_version_requirement: ^9.4
In the previous 2 examples, the
core key is removed, replaced entirely by
core_version_requirement. The module is not compatible with versions of Drupal prior to 8.7.7 in the first example and only version of Drupal 9.1 and higher in the second case.
Why use a more granular
- If a particular minor or patch release of Drupal contains a bug or security fix that you want to ensure is in place before your module is installed.
- A core feature that your module depends was introduced within a minor version release cycle.
Convey stability with
Introduced in Drupal 9.3.x, you can use the
lifecycle_link keys to describe the stability of a module (or theme).
Supported values for
lifecycle are as follows:
- experimental: Something new and not finalized. The user receives a warning about its experimental status if you try to install them, but the module works.
stable: The default value for
lifecycle. Stable Drupal extensions with no special warnings or behavior.
deprecated: Something on the way out in the next major release. You can still install it, but administrator(s) receive warnings if deprecated extensions are installed on the site. (Also provide
lifecyle_linkkey with link to documentation or change record.)
obsolete: Really gone. You should uninstall it. If it's already installed, administrator(s) will see warnings. New installations are prohibited. (Also provide
lifecyle_linkkey with link to documentation or change record.)
obsolete lifecycle states, a
lifecycle_link key is also required. The
lifecycle_link key should specify a URL to documentation regarding its deprecation or obsolete status. This helps site builders and administrators know what to do with deprecated or obsolute modules installed on their site.
See the change record, Info files can now contain 'lifecycle' and 'lifecycle_link' keys to convey the stability of a module/theme, for more information and examples.
After you install (enable) the module, notice that our Hello World module has been added to a new group called Other on the module administration page. We can specify a different name for this group for organizational purposes by using the
package key in our info file if desired:
The YAML info file can also specify dependencies on other modules. If our custom module will require code from other modules, whether core or contributed, we can explicitly list them. When dependencies are specified Drupal will not allow your module to be installed unless the dependencies can be satisfied. This may be achieved by first installing other available modules, or Drupal may tell you that you need to download another contributed project before your new module can be enabled.
Dependencies should be a list of dependencies with the format
project is the machine name of the project as it appears in its Drupal.org project page URL and
module is the machine name of the module, which can be derived from the directory name that houses the module's code. Many times the project and the module name will be identical, but sometimes a project will contain several modules with distinct functionality. Use project name
drupal for modules in the core/ directory.
List a core module as a dependency
- Project: Drupal (core)
Module machine name(s):
- Installed at: core/modules/node
To list the Node module as a dependency for your module, add the following to your module's info file:
dependencies: - drupal:node
List a contributed module as a dependency
- Project: Webform
- Module machine name(s): webform
- Installed at: modules/contrib/webform
To list Webform module as a dependency for your module, in your module's info file, add the following:
dependencies: - webform:webform
List a sub-module of a project as a dependency
- Project: Devel
Module machine name(s): main module:
- Installed at: modules/contrib/devel, modules/contrib/devel/devel_generate, modules/contrib/devel/webprofiler
To list Devel Generate, one of the modules contained within Devel, as a dependency for your module:
dependencies: - devel:devel_generate
You can also define version restrictions on any listing. This will result in a warning on the status report page that a module is incompatible with the core version. (Note: you should probably use the root-level key,
core_version_requirement, to specify core version compatibility with your module instead of
Here is a complete example of what these dependencies would look like in our demo module's "info" file:
name: Hello World description: A silly example module type: module core_version_requirement: ^8 || ^9 || ^10 dependencies: - drupal:node - webform:webform (>=8.x-5.x) - devel:devel_generate
In this case we're telling Drupal that our module cannot be installed unless the core Node module is enabled and the contributed modules Webform and Devel Generate are enabled as well. Also, we're indicating with the
core_version_requirement key that the module is compatible with 8.7.7 and higher, or Drupal 9. (
drupal:system (>=8.7.7) is still supported).
What about composer.json?
If you're contributing your module back to the community and you want DrupalCI to test module dependencies for your module, you'll need to list your module's dependencies in a composer.json in the module's root directory, in addition to listing dependencies in the info file. See Add a composer.json file on Drupal.org.
Point to settings form route with
The other main key you may find in info files is
configure. Use this only if your module needs to provide particular configuration settings that are exposed to the site administrators. The
configure key in your module's info file specifies the route that will be used to navigate to the module's configuration settings form. A link to this configuration form will automatically be added to the module's listing on the Extend (admin/modules) page in the extended information about your module. For example, the Search API module uses this value to provide a link to its configuration form.
And the corresponding search_api.info.yml file:
type: module name: 'Search API' description: 'Provides a generic framework for modules offering search capabilities.' package: Search core_version_requirement: ^8.8 || ^9 lifecycle: stable configure: search_api.overview
If you look at other info YAML files, especially from contributed modules you might notice additional key/value pairs. In particular, Drupal.org's packaging script adds information about the specific version and a datestamp for when that module was generated. None of this metadata is required in a custom module you develop, but can be useful when troubleshooting during development.
In this tutorial, we looked at the main elements that make up info files for Drupal modules. This type of file is required in order for Drupal to recognize our code as a module, and to get it to show up on the module's listing on the Extend page. At a minimum our info file needs to provide the
core_version_requirement keys. Additional metadata specifying the dependencies of our module, the route to the configuration form may also be added.
Further your understanding
- Take a look at the MODULE.info.yml files included with core and contributed modules on your site. Are there any additional options this tutorial doesn't cover?
- Use Drupal Console to generate a module. Look at the YAML file it generates. Are there any differences there?
- Introduction to YAML (Drupalize.Me)
- Develop Drupal Modules Faster with Drush Code Generators (Drupalize.Me)
- Semantic Versioning (Drupalize.Me)
- Change record: New 'core_version_requirement' key in info.yml files for modules and themes allows Composer semantic version constraints including specifying multiple major versions of core (Drupal.org)
- Drupal 8.7.7+ will support extensions compatible with both Drupal 8 and 9! (hojtsy.hu)
- Change record: info.yml files no longer accept 'core: 9.x' (Drupal.org)
- To check the Drupal 9 readiness of your module, install and run the Upgrade Status module (Drupal.org)
- Add a composer.json file Drupal.org
- Info files can now contain 'lifecycle' and 'lifecycle_link' keys to convey the stability of a module/theme (Drupal.org)