After working with drupal for years I am amazed by the number of custom modules out there and what they have unleased for business’s that have used them and continue to innovate more. The ones I refer to here are the publicly accessable ones, I believe there are just as many which are private and are highly specialised to the business that have them developed. This is the use case I am wanting to target here. These Custom Modules are ones you can create for a clients specific needs.
In Drupal 9 custom modules off there flexibility to create entirely new features and/or adjust existing ones to enhance a business’s growth or open up new lines of what they offer. It allows virtually unlimited creativity and possibility for owner of a Drupal system. For Developers if offers then a way to provide highly novel solutions for those busssiness.
The aim of this article is to help you build your first basic custom module in Drupal 9. Note these will also work for Drupal 8 ( D8 is end of life and migration plans ideally would be underway, if not, reach out to me and we may be able to work together on it)
Drupal 9 Module development
Lets getCoding! and create this module in just a few phases.
Phase 1: The Name
A great place to start is to decide on the name of your module and then we can create it under the folder path “/modules/custom”. The one ill choose for this article is “simple_module“. You will notice my root folder is called drupal_tutorals yours may be configured as web, root or something else
Rules for naming:
- start it with lower case letters, (simple_module, not, Simple_Module)
- no spaces in the name. ( simple_module, not, simple module)

done!, lets get onto the next phase
Phase 2: Create info.yml file ( for Drupal to recognise it)
Next we need to create a .yml file. If you are unfamiliar with what a .yml ( or .yaml) file is it is a format that is great for storing configuration it is a superset of JSON and not a markup language, if you want to learn more about JSON read this article.
So in short the .yml is a configuration file for our module which allows drupal to know about it. We create a file in our new folder (simple_module) and call it simple_module.info.yml, put the following code into it
name: Simple Module
type: module
description: 'Demo a creating a simple Drupal 9 Module.'
package: Custom
version: 0.5
core_version_requirement: ^8 || ^9
Lets look at what each of these config items is
name: This is the name that will get displayed in the modules list in our Drupal admin section
type: this will be either module or theme, in our case module
description: a longer description of the module that will appear in the Drupal admin section under the name
package: specify this as being custom module
version: this is our module version, I have put 0.5 as it is in dev, for a full ready release it should go out as 1.0 )
core_version_requirement: let it know which versions of Drupal this will work with ( 8/9)
That is our config done! Nice we are almost there now we just need to add our Router file and our controller!
Phase 3: Create Module Routing, routing.yml
I really like the routing system in Drupal 8/9, it replaces the routing parts of the hooks_menu() that was in Drupal 7. The routing system is mostly based on Symfony’s, so where I say mostly it can do everything that Symfony’s can and more, both Drupal 8/9 and Symfony use the same syntax to define routes.
In short: Routing is where our pages will be accessed via URL’s
Create a file simple_module.routing.yml in our simple_module folder and add the following
simple_module.demopage:
path: '/simple/demopage'
defaults:
_controller: '\Drupal\simple_module\Controller
\SimpleController::demopage'
_title: 'Simple Demo page for Drupal 9'
requirements:
_permission: 'access content'
So lets unpack what we have here in the simple_module.routing.yml file
Line #1: is the route name
Line #2: The URL page this route will be regestered to eg https://demo.com/simple/demopage
Line #4: Is a reference to the _controller and a demopage class() that is within this controller ( we will be making this file next)
Line #5: The _title ( default title ) of the page for the controller we specify in Line #4
Line #7: List of _permission that are needed to access the module, here we just want a public page so access content is the only one needed, if we were creating an admin page or something within a user profile then we would add some more restrictive permissions
So far we have now got the shell of our module ( phase 1 & 2 ) the routing information of where to access the page we are making ( phasev3) . Now for our final phase.
As mentioned on Line #4: The controller is what we need next so that we can build out the meat of our custom module and put in the actual behavours of what will be on the page this is what our controller will do
Phase 4: Create a Controller
In the folder we created in step 1 (/modules/custom/simple_module) we need to create some additional folders
(/modules/custom/simple_module/src/Controller) and also a file “SimpleController.php” and in it put the following
<?php
namespace Drupal\simple_module\Controller;
class SimpleController {
public function demopage() {
return array(
'#markup' =----> 'Congratulations, you have made your a Custom Module in Drupal 9!</br>Time to Celebrate!</br>Don't forget to reward yourself!'
);
}
}
From here we are done with the code!
Your files should look something like this

Log into your Drupal installation and enable the simple module we just created. As always we need to check that what we have done works so navigate to /simple/demopage , you may need to clear the cache if it does not work.
admin / configuration / performance and then clear cache on that page.
Try the location /simple/demopage again.

Thats the end. Whilst the module itself does not do anything you now are able to create a custom module and then implement what it is your client or company needs.
You can access the code for this module at this GitHub repo