
Last Updated on June 10, 2026
Are you looking to create a custom Joomla module for your website? In this tutorial, you’ll learn how to develop a Joomla 5 and Joomla 6 module from scratch using modern Joomla development standards.
By the end of this guide, you’ll understand how to create a custom module, organise files correctly, add module parameters, retrieve data from the database, and display dynamic content on the frontend.
This tutorial is designed for beginners as well as Joomla developers who want to build custom extensions using the latest Joomla framework architecture.
What Is a Joomla Module?
A Joomla module is a lightweight extension used to display content or functionality in predefined template positions.
Examples of Joomla modules include:
- Login Form
- Latest Articles
- Popular Articles
- Custom HTML Content
- Search Module
- Image Sliders
- Menus
- Tags Module
Unlike components, which control the main content area, modules can appear in various locations such as sidebars, headers, footers, and custom template positions.
Joomla Module vs Component vs Plugin
| Extension Type | Purpose |
|---|---|
| Component | Controls the main content area of a page. |
| Module | Displays content in template positions. |
| Plugin | Executes code when Joomla events are triggered. |
Before learning module development, you may also want to read:
Requirements
Before creating your first Joomla module, make sure you have:
- Joomla 5.x or Joomla 6.x installed
- PHP 8.1 or higher
- Administrator access to Joomla
- Basic PHP knowledge
- A code editor such as VS Code or PhpStorm
Module We Will Build
In this tutorial, we will create a custom Joomla 6 module called mod_servicesgrid.
The module will:
- Display a responsive grid of services on the frontend
- Allow administrators to add and manage service items through the module settings
- Support service titles, descriptions, icons, images, and links
- Use Joomla 6 coding standards and PSR-4 autoloading
- Support language files for multilingual websites
- Use a Helper class for data processing and business logic
- Use layout files for clean separation of logic and presentation
- Support template overrides for easy customization
- Be fully installable as a standard Joomla extension
- Follow Joomla 6 extension development best practices
By the end of this tutorial, you will have a modern, reusable Services Grid module that can be easily customized and deployed on any Joomla 6 website.
Step 1: Create the Module Folder Structure
Create a new folder named mod_latestposts.
Your module directory should look like this:
mod_servicesgrid/ │ ├── mod_servicesgrid.php ├── mod_servicesgrid.xml │ ├── forms/ │ └── service.xml │ ├── tmpl/ │ └── default.php │ ├── media/ │ └── css/ │ └── style.css │ └── language/ └── en-GB/ ├── en-GB.mod_servicesgrid.ini └── en-GB.mod_servicesgrid.sys.ini
Directory Explanation
| Directory/File | Purpose |
|---|---|
mod_servicesgrid.php | Main entry point of the module. Loads the helper, retrieves module data, and renders the layout. |
mod_servicesgrid.xml | An installation manifest file that defines module metadata, files, folders, and configuration parameters. |
tmpl | Contains frontend layout files used to render the services grid output. |
language | Stores language and translation files for multilingual support. |
services/provider.php | Registers the module with Joomla’s Dependency Injection (DI) container and service provider system. |
media | Optional directory for module-specific CSS, JavaScript, images, and other frontend assets. |
Step 2: Create the XML Manifest File
Create a file named: mod_servicesgrid.xml
This file tells Joomla how to install and configure the module. It provides the following information about the module:
- Module name
- Version
- Author information
- Files to install
- Language files
- Module parameters
Without this file, Joomla cannot install the module.
Add the following code:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" client="site" method="upgrade">
<name>MOD_SERVICESGRID</name>
<author>Sanjeev Kumar</author>
<version>1.0.0</version>
<description>MOD_SERVICESGRID_DESC</description>
<files>
<filename module="mod_servicesgrid">mod_servicesgrid.php</filename>
<folder>tmpl</folder>
<folder>forms</folder>
<folder>media</folder>
<folder>language</folder>
</files>
<languages>
<language tag="en-GB">language/en-GB/en-GB.mod_servicesgrid.ini</language>
<language tag="en-GB">language/en-GB/en-GB.mod_servicesgrid.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic" label="MOD_SERVICESGRID_SERVICES">
<field name="services" type="subform" multiple="true" formsource="service.xml" label="MOD_SERVICESGRID_SERVICES" />
</fieldset>
</fields>
</config>
</extension>What Does the Manifest File Do?
- Defines module metadata.
- Registers files and folders.
- Registers language files.
- Creates module parameters.
- Controls installation and updates.
In the next section, we’ll create the main module file (mod_servicesgrid.php) and build the helper class that retrieves articles from the Joomla database.
Step 3: Create the Main Module File
The main module file serves as the module’s entry point. Joomla executes this file whenever the module is rendered on the frontend.
file name is mod_servicesgrid.php, and add the following code:
<?php
defined("_JEXEC") or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\ModuleHelper;
$wa = Factory::getApplication()
->getDocument()
->getWebAssetManager();
$wa->registerAndUseStyle(
'mod_servicesgrid',
'modules/mod_servicesgrid/media/css/style.css'
);
$services = (array) $params->get('services');
require ModuleHelper::getLayoutPath(
'mod_servicesgrid',
$params->get("layout", 'default')
);Responsibilities:
- Prevent direct access.
- Retrieve module parameters.
- Load required assets.
- Load the layout file.
Example workflow:
- Joomla loads module.
- Parameters are retrieved.
- CSS file is loaded.
- Layout file is rendered.
This file should remain lightweight.
Step 4: Create the Service Subform
File:forms/service.xml
Instead of creating fixed service fields, we’ll use a Joomla Subform.
Benefits:
- Add unlimited services.
- No code changes required.
- Easy administration.
Each service can contain:
- Title
- Description
- Icon
- Link
The administrator can click “Add Service” to create additional service entries.
This makes the module highly flexible.
Add the following code: you can see after the first line, there are added comments that are standard but not required.
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Service Subform Definition
*
* @package Joomla.Site
* @subpackage mod_servicesgrid
* @since 1.0.0
*/
-->
<form>
<fields name="item">
<field
name="title"
type="text"
label="MOD_SERVICESGRID_TITLE"
required="true"
/>
<field
name="image"
type="media"
label="MOD_SERVICESGRID_IMAGE"
/>
<field
name="description"
type="textarea"
label="MOD_SERVICESGRID_DESCRIPTION"
/>
<field
name="link"
type="url"
label="MOD_SERVICESGRID_LINK"
/>
</fields>
</form>Step 5: Add Module Parameters
Inside the manifest file create a subform field.
Example configuration:
- Services Field
- Multiple = true
- Form source = service.xml
When the module settings are opened, Joomla automatically loads the subform and displays repeatable service fields.
The entered data is stored in the module parameters JSON.
Example: This code is already added in the main file mod_servicesgrid.xml.
<config> <fields name="params">
<fieldset name="basic" label="MOD_SERVICESGRID_SERVICES">
<field name="services" type="subform" multiple="true" formsource="service.xml" label="MOD_SERVICESGRID_SERVICES" />
</fieldset> </fields> </config>Step 6: Create Language Files
Files:
language/en-GB/en-GB.mod_servicesgrid.ini
language/en-GB/en-GB.mod_servicesgrid.sys.ini
en-GB.mod_servicesgrid.ini
Contains:
- Field labels
- Descriptions
- Frontend text
Example:
MOD_SERVICESGRID=”Services Grid”
MOD_SERVICESGRID_SERVICES=”Services”
en-GB.mod_servicesgrid.sys.ini
Contains:
Module name
Module description
Example:
MOD_SERVICESGRID=”Services Grid”
MOD_SERVICESGRID_XML_DESCRIPTION=”Displays services in a responsive grid.”
Using language files makes your extension multilingual and Joomla-standard compliant.
Step 7: Create the Frontend Layout
File:
tmpl/default.php
This file controls the HTML output.
Responsibilities:
Read services data.
Loop through service items.
Generate grid markup.
Display titles and descriptions.
Typical process:
Read module parameters.
Decode subform data.
Loop through services.
Display service cards.
This keeps presentation separate from business logic.
Step 8: Add CSS Styling
File:
media/css/style.css
This file controls the appearance of the services grid.
You can style:
Grid layout
Card spacing
Hover effects
Typography
Mobile responsiveness
Recommended design:
3 columns on desktop
2 columns on tablet
1 column on mobile
Keeping styles in a separate CSS file makes future customization easier.
Step 9: Load CSS Assets
Register the stylesheet from the module entry file.
Purpose:
Ensure CSS loads only when the module is used.
Improve maintainability.
Follow Joomla 5/6 best practices.
The CSS file should be loaded using Joomla’s Web Asset Manager whenever possible.
Step 10: Package the Module
Before installation, verify:
Required Files
mod_servicesgrid.php
mod_servicesgrid.xml
forms/service.xml
tmpl/default.php
media/css/style.css
language files
Create ZIP Package
The ZIP root must contain:
mod_servicesgrid.xml
mod_servicesgrid.php
forms/
tmpl/
media/
language/
Do not place everything inside an extra folder when creating the ZIP.
Step 11: Install the Module
Navigate to:
System → Extensions → Install
Upload:
mod_servicesgrid.zip
If installation succeeds:
- Create a new module instance.
- Select a module position.
- Assign menu items.
- Publish the module.
Step 12: Add Services
Open the module settings.
You will see the Services Subform field.
Click:
Add Service
Fill in:
Service Title
Description
Icon
Link
Add as many services as needed.
Save the module.
Step 13: Test the Frontend
Visit the frontend.
Verify:
Services display correctly.
Grid layout is responsive.
Language strings load correctly.
Styling is applied.
Also test on mobile devices.
Step 14: Troubleshooting Common Errors
Language File Missing
Cause:
Incorrect language path.
Missing language files.
Solution:
Verify language folder structure.
Class “JText” Not Found
Cause:
Using Joomla 3 code.
Solution:
Use:
use Joomla\CMS\Language\Text;
Form::getInstance() Could Not Load File
Cause:
Subform XML file missing.
Solution:
Verify:
forms/service.xml
exists and is included in the manifest.
Module Not Displaying
Cause:
Module unpublished.
Wrong position.
Menu assignment issue.
Solution:
Check module settings and template positions.
Conclusion
You have successfully created a Joomla 5/6 Services Grid Module using:
Custom module architecture
Joomla Subforms
Language files
Responsive CSS
Joomla best practices
This foundation can easily be expanded to include icons, images, animations, AJAX loading, or custom field types for more advanced projects.


