Menu
Kevin's Guides

Developing a Joomla Template

Developing a Joomla Template
Write a comment

Developing a Joomla Site Template

In this extensive guide, you will learn how to create your own custom Joomla template (Joomla 4 or 5). You must already know the basics of Joomla, HTML, and CSS. I'll explain just about everything else.

Prerequisites: You must have Joomla 4/5 set up on a test server (ideally, a local test server or your own PC). You must have a basic to mid-level understanding of HTML and CSS. Knowledge of PHP, JavaScript, and Bootstrap 5 is a plus, but not a direct requirement.

If you're not familiar with Bootstrap, it's a CSS/JS framework that allows you to easily add things like dropdowns, grid systems, containers, accordions, tabs, and more to your website. It's used by most of the core Joomla extensions and many third party extensions. I'd highly recommend you familiarize yourself with it if you haven't done so already. You can learn more and see specific examples at getbootstrap.com.

Some of the basics of Bootstrap will be reviewed here. However, it's not inherently necessary to build a Joomla template. If you want to learn more about why I recommend you learn Bootstrap, here's a video I made. If you already know how to use Bootstrap, just skip that part!

 

Getting Started

Before you begin, set up Joomla in a local test environment using XAMPP or similar software.

Next, download and install the JoomStarter template on your test server using Joomla's extension installer.

If you don't want to bother reading this guide or learning Bootstrap/Sass, and just want to start with the simplest template possible, you can also try my JoomSkeletal template. It's the most basic Joomla template you could possibly create, with 4 files all in a single folder and no dependencies.

I assume you already have a code editor installed. You may use whichever one you prefer, so long as it supports HTML/CSS/PHP. Visual Studio Code is my first suggestion, and the one that will be referenced in this guide.

Finally, make sure you have Sass ready to go. If you do not know what Sass is, it's a CSS preprocessor that we'll need to compile the multiple stylesheets our template uses into one. It's free and relatively easy to use. Click the button below if you need help installing.

Full SASS Guide

Installing NodeJS and Sass

Sass is a program which adds additional functionality to stylesheets. We need it to combine our Bootstrap and Template stylesheets together.

Before you can install Sass, you must first install NodeJS. If you don't know what NodeJS is - it's basically a JavaScript library that lets us execute JavaScript on our PCs (outside the browser). There are alternative ways of installing Sass without NodeJS, but NodeJS is a very standard web development tool. So you should probably have it installed anyways, as you'll likely need it for something else down the road.

So to begin, download and install NodeJS if you don't already have it. The easiest way is from the NodeJS.org website.

Once you install NodeJS, open a command prompt window (terminal, powershell, whatever). Execute this command (type and hit enter)

npm install -g sass

NPM stands for Node Package Manager, it's a tool that allows us to easily install the apps (or dependencies) we need (like Sass) to develop our software with. The "install" part just means - install this, the -g means install it globally (so it can be run from anywhere), and finally "sass" is sass. Wait for it to finish.

Close the terminal/command prompt window when complete. That is all for now.

Once you have joomstarter installed on Joomla, Sass installed, and your favorite code editor setup, you're ready to develop the template!

 

What's JoomStarter

JoomStarter (formerly j4starter - you may see old references to this name) is a sample template I created to provide you with a base to build your template off of. It includes all the files needed for a basic template.

Download and install JoomStarter in Joomla using the extension installer, if you have not done so already.

Next, set joomstarter as your default template style from the Joomla template style manager.

As you can see, there's not much to this template to begin with. You must style it using HTML and CSS.

joomstarter defaultjoomstarter on the frontend

 

Examining The Files

Next, it's time to look at the template files themselves, so you know what you're dealing with.

The Templates Folder

The files used by joomstarter have been scattered across your Joomla directory, in a few different locations. Some of the most important template files may be found in the templates folder at site_root/templates/joomstarter

joomstarter templates directoryMy templates/joomstarter folder

Each of these files/folders serves a specific purpose.

  • index.php
    • Very important. It's the file containing the core HTML/PHP code of your template.
  • templateDetails.xml
    • Very important. It's the file containing your website's details (title, description, folder structure, and more) that Joomla looks at when installing the template.
  • joomla.asset.json
    • This is where we're supposed to tell Joomla where important web assets are stored, such as the template CSS and JavaScript files.
  • language folder
    • This is where Joomla loads language-specific information from. The title of your template in English, and its basic description, for example. Note that this is where Joomla gets its copy of the language files from. The language files in active use are stored under site_root/language/lang-code/tpl_joomstarter.ini
  • html folder
    • This contains the HTML template overrides to be used with joomstarter. Joomla has default templates/layouts for every module and component on the website. You can change how they are displayed using overrides placed in this directory.

The Media Folder

All important media files (CSS, JavaScript, images, etc.) are stored in the media folder at site_root/media/templates/site/joomstarter

The media folder for your template contains 4 additional folders. One for the CSS files, one for JavaScript files, one for images, and one for SCSS (Sass) files.

 

Examine index.php

The index.php file under site_root/templates/joomstarter contains all the PHP and HTML used to generate your template. As mentioned earlier, you do not need to know any PHP to complete this guide, but you will need to learn a few basic things about it. I'm writing this guide with the assumption that you don't know any PHP. If you do, you may gloss over some things.

The Beginning (Comments and Info)

Open index.php using your favorite editor and look at it.

<?php
/**
 * @package     Joomla.Site
 * @subpackage  Templates.joomstarter
 *
 * @copyright   (C) YEAR Your Name
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * This is a heavily stripped down/modified version of the default Cassiopeia template, designed to build new templates off of.
 */

The first few lines at the top are all commented out. This is just general information about the template. It's your choice if you'd like to replace what is here with your own name, copyright, etc. It does not affect the functionality of the template.

The <?php shows that this is the start of the PHP code. Do not change this line. It is required. The asterisks with the forward slashes /** ... */ show the start and end of a PHP comment. PHP comments are ignored by the program.

Using Other Classes

The next few lines look like this. You do not need to change anything here.

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

/** @var Joomla\CMS\Document\HtmlDocument $this */

The first line defined('_JEXEC') or die; is a security measure. Essentially, it means only Joomla can execute this file. Users cannot directly open the templates/joomstarter/index.php file in their browser and see anything.

The following lines with the use keywords tell Joomla to use some other class files that are built into Joomla. These are other files the template needs to work. The last line was commented out, I think it's a depreciated class from Joomla 3. You may delete it or ignore it.

Loading WebAssetManager

The next two lines have to do with the WebAssetManager.

$app = Factory::getApplication();
$wa  = $this->getWebAssetManager();

The WebAssetManager does what its name says it does - manages assets. We can use the WebAssetManager to add JavaScript and CSS assets to our template with more code.

If you'd like a more in-depth look at the WebAssetManager, please see the guide on that subject.

Add Favicon

The next line deals with the site's favicon. The little icon shown in the tab at the top of the screen, or when people bookmark your page on their computers or phones.

$this->addHeadLink(HTMLHelper::_('image', 'favicon.ico', '', [], true, 1), 'icon', 'rel', ['type' => 'image/x-icon']);

This is telling Joomla to add a link to the favicon.ico file in the page heading. The icon is sourced from site_root/media/templates/site/joomstarter/images

You do not need to change anything with this line either, unless you rename your favicon file. You should be fine just editing the favicon file in the template's media folder.

Active Variables

The active variables will change to represent information from the page the user is currently on.

// Detecting Active Variables
$option   = $app->input->getCmd('option', '');
$view     = $app->input->getCmd('view', '');
$layout   = $app->input->getCmd('layout', '');
$task     = $app->input->getCmd('task', '');
$itemid   = $app->input->getCmd('Itemid', '');
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
$menu     = $app->getMenu()->getActive();
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';

For example, the $itemid variable contains the value of the page's item id from the database. The $sitename is the name of the site set in the Global Configuration. The $pageclass is the CSS class of the page set in the menu item options. Do not make any changes here.

Test Parameter

Joomla allows us to easily add parameters to our template if we want to make them customizable by the users installing them. For example, if you want your template to have a green and a red style, you could add multiple stylesheets and styling options. Then the user can pick what style they want to use in the template style options. We will discuss this in more detail later. The joomstarter template comes with one "test" parameter that I have included. This line loads that test parameter and does nothing with it.

//Get params from template styling
//If you want to add your own parameters you may do so in templateDetails.xml
$testparam =  $this->params->get('testparam');

Template Path

This line gets the path of the current template, relative to the site root.

// Get this template's path
$templatePath = 'templates/' . $this->template;

It may be useful down the road.

Load Bootstrap Component

The next line loads a single Bootstrap component. Specifically, the javascript for the collapse component. This is required to use the Bootstrap menu layouts I provided with joomstarter. If you plan on using the included menu system, leave this alone.

HTMLHelper::_('bootstrap.collapse');

Register WebAssets

The next three lines load the WebAssets defined in the joomla.asset.json file. By default, these are "template.min.css" and "template.js" from the CSS and scripts folder under the template's directory in the media folder. Leave these alone, unless you need to add additional asset files down the road.

//Register our web assets (CSS/JS)
$wa->useStyle('template.joomstarter.mainstyles');
$wa->userStyle('template.joomstarter.user');
$wa->useScript('template.joomstarter.scripts');

Note: As of version 1.17, I have added a "user.css" file which you may edit without knowledge of SASS/SCSS. You can just overwrite existing styles in this file. It's located at media/templates/site/joomstarter/css/user.css

If you're curious about how the WebAssetManager found the files, or you want to add additional files, review the above code and the joomla.asset.json file.

The joomla.asset.json file contains the actual relative link to the file.

joomla.asset.json
    {
      "name": "template.joomstarter.user",
      "description": "The custom css style to use. Must be placed in media/templates/site/joomstarter/css/user.css",
      "type": "style",
      "uri": "user.css"
    },

The above code came from the joomla.asset.json file. This is giving this asset the name "template.joomstarter.user", informing Joomla that it's a "style" and telling it the filename is "user.css"

When we call...

$wa->userStyle('template.joomstarter.user');

On line 54 of index.php, it's telling Joomla to go to joomla.asset.json, find the asset named "template.joomstarter.user" and load it. Since "template.joomstarter.user" links to "user.css" the user.css file is loaded.

Set Viewport

The template sets a default viewport using the standard arguments. You should be familiar with what viewports are. If you need to change anything here, you may do so. The parameters I set are pretty standard.

//Set viewport
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');

The Template's HTML Begins

After the last line, there is a closing statement for PHP. ?> Leave that as is. That means it's the end of the main PHP block in our code. The code coming below that is the start of the template's HTML.

The start of the template's HTML begins with a standard declaration of the document type, along with the head element.

<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
	<jdoc:include type="metas" />
	<jdoc:include type="styles" />
	<jdoc:include type="scripts" />
    
</head>

You should leave this section alone too, unless you know what you're doing. The jdoc:include sections within the head element load all the scripts, styles, and metadata defined in the PHP above. Anywhere you see the php tags with an echo statement means that the template is using PHP to insert something here. <php echo $variableName; ?> In this scenario, it's adding the language code of the template (en-GB or en-US, for example) and the direction of the text (left to right or right to left) as defined in the site settings.

The Body

Finally, we get to the body of the HTML. This is where you can write your own HTML to define the template's layout and place elements within the page.

The joomstarter template includes a very primitive layout using a Bootstrap 5 container and grid. It's up to you if you'd like to delete this all and make your own layout, or build off the one I provided to you. I will explain the process of creating a sample layout from scratch after we cover how the CSS works.

 

Using CSS/Sass

As I mentioned before, the best way to work on your site's CSS and Bootstrap is with the use of the CSS preprocessor SASS. Please install it if you have not done so already. I'm going to show you how to use it.

You can skip this part if you don't want to learn or use Sass. However, I highly recommend it if you plan on becoming a better web developer. I've also posted a video on why you should learn Bootstrap and Sass if you're curious.

Sass can take a collection of stylesheets saved as .scss files and compile them into a single compressed stylesheet - template.min.css. It can do much more than that, but that's what we'll focus on for now.

The stylesheets can be found under the template media folder at site_root/media/templates/site/joomstarter/css and site_root/media/templates/site/joomstarter/scss

We are going to be adding our template's custom styles to the template.scss file at site_root/media/templates/site/joomstarter/scss/template.scss and using SASS to compile that file into site_root/media/templates/site/joomstarter/css/template.min.css

Our template will then load the template.min.css file when a page is displayed.

The scss files for Bootstrap 5 are included with this template. We are going to compile and add them all to our template using Sass. So both our template's CSS styling and Bootstrap's CSS styling will ultimately become part of template.min.css in the media/.../css folder.

Sass Command and Test Style

Now, you need to test out Sass and make sure you know how it works. To do this, we're going to change the template.scss file at site_root/media/templates/site/joomstarter/scss/template.scss and compile it into the template.min.css file.

Open template.scss and look at it.

//This is where you can edit your Css, or better yet, create additional scss files and import them.
//You can compile this to css using the command: sass template.scss:..\css\template.min.css --style compressed

// Load our local copy of Bootstrap 5.3
@import "vendor/bootstrap/functions";
@import "vendor/bootstrap/variables";
@import "vendor/bootstrap/bootstrap";

//Your Imports Here

//Your Css Here

This file contains some import statements, along with comments. The import statements import the Bootstrap scss files from the vendor/bootstrap folder under site_root/media/templates/site/joomstarter/scss

Leave the import statements alone, unless you don't plan on using Bootstrap anywhere on your website. Bootstrap is a requirement for most extensions to work, unless you plan on heavily customizing every last aspect of your website.

Now, let's make a modification to the template's body style, so we can see how sass works.

Under the //Your Css Here section of the template.scss file, add some lines to change the body color of the template. By default, the body color is white. I'm going to change it to blue for a simple demonstration.

Now, my template.scss file looks like this:

//This is where you can edit your Css, or better yet, create additional scss files and import them.
//You can compile this to css using the command: sass template.scss:..\css\template.min.css --style compressed

// Load our local copy of Bootstrap 5.3
@import "vendor/bootstrap/functions";
@import "vendor/bootstrap/variables";
@import "vendor/bootstrap/bootstrap";

//Your Imports Here

//Your Css Here
body{
    background: blue;
}

Make sure you save the changes. If I reload my website's home page, nothing happens yet. I still see the old stylesheet. This is because I have not used Sass to compile the template.scss file into the template.min.css file, as needed.

To compile the scss file, open command prompt with ruby (or terminal on Mac/Linux). Then, change the directory in the command prompt to the template's SCSS folder.

In windows, the command is

cd DIRECTORY

where DIRECTORY is the directory we are navigating to.

 

When the command prompt opens, you are in the C drive by default in Windows. If your test environment files are also under the C drive, you do not need to change your drive. If your computer has multiple drives like mine does, and your test environment is on a different drive, you must change the drive first. To change the drive, just type the drive letter followed by a colon, like so. I'm using the D drive on my computer.

d:
change driveChange drive if needed

Now, we can use the cd command to change the directory to the scss folder. On my computer, my SCSS folder is at D:\xampp\htdocs\joomla\media\templates\site\joomstarter\scss

Copy the directory of wherever the scss folder is on your computer.

copy scss folderCopy the SCSS folder address

In the console, type

cd your_directory

 

Note, to paste the directory in a command prompt, you must use the SHIFT and INSERT keys to paste something (not CTRL + V). Alternatively, you can type "cd " and then right click. There must be a space between cd and your directory. When you right click, the copied directory will be pasted.

command change directory to scss folderChange to scss folder

Once you're in the scss folder, you can run sass to compile the scss file into template.min.css.

The command to compile ONE TIME is:

sass template.scss:..\css\template.min.css --style compressed

This tells Sass to compile the template.scss file into a minified, compressed template.min.css file in the parent /css directory.

This may take a few seconds, as it has a lot of Bootstrap files to process. If you don't see any error messages, that means it worked successfully. You may re-compile by using the same command (press up arrow key then enter to use last command in console).

sass compile success

Now, you can look at your media\templates\site\joomstarter\css folder and see if template.min.css was updated by checking the last modified time of the template.min.css file.

Since I made my background blue, when I reload my home page on the test site, the background is blue. The navbar at the top looks the same. That was a Bootstrap navbar, so I know it loaded the Bootstrap files correctly.

home changed body blueMy ugly change worked!

Now, you can make any changes you want to the template.scss file to style your template. Run the:

sass template.scss:..\css\template.min.css --style compressed

command each time you make a change you need to be updated. So leave your console open.

sass --watch

Alternatively, you can use the sass --watch argument. The watch argument watches for changes to the source file and automatically updates the output when a change is detected. So whenever you save the .scss file, the .css file will be updated with it. This is likely the better option if you're going to be making changes often and want to preview them in the browser.

You can do this by running this command, from within the scss directory. Leave the console window open or it will stop watching for changes. So you must do this every time you change the stylesheet.

sass --watch template.scss:..\css\template.min.css --style compressed
saass watchRunning sass --watch

I changed the background color of my body from blue to white. Then I checked the console to make sure Sass updated the CSS file. If your changes are not reflected when you reload your local website, make sure your browser caching is disabled. In Chrome you can disable the cache through the developer tools. Go to the Network tab. There's a "Disable Cache" option at the top. Reload and your changes should be reflected.

 

Basic Template Example

Now that you understand how Sass works, we can return to working on the template's HTML in index.php. I'm going to show you how to create a basic layout and display modules/components on the template.

So open the index.php file for the joomstarter template under site_root/templates/joomstarter if you closed it.

The Wireframe

For demonstration, I'm going to be creating a very simple template with a Bootstrap Grid.

Here's a basic wireframe of the layout I'm going for. Nothing fancy. It will not look pretty, but it will work.

sample template layout

I'm going to go back and forth between the index.php file and the template.scss file. Remember to save your changes, and check that any changes you make to the stylesheet are being watched with the sass --watch command explained previously.

Remove The Body

First, delete the contents of the body section of the index.php file, we're going to start our new layout from scratch.

<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
	<jdoc:include type="metas" />
	<jdoc:include type="styles" />
	<jdoc:include type="scripts" />
    
</head>

<body class="site">
	
</body>
</html>

Create The Container/Title

The first thing I'm going to add to my website is a container. A container class contains a grid in Bootstrap. I will not describe every detail of how Bootstrap grids work here, but I will explain the basics to help if you're new.

<body class="site">

<div class="container">
    
</div>
	
</body>

The next thing at the top of my template wireframe is the name of the site. To add this to my template, I'm going to display the site name in a centered span with a font size of 2 rem. I'm giving it the id of site-title so I can easily target it from my stylesheet.

index.php body section
<body class="site">

<div class="container">
    <span id="site-title"><?php echo $sitename ?></span>
</div>
	
</body>

The PHP code <?php echo $sitename ?> was added to display the site name variable within the span element.

Now, I've added this code to my template.scss file to style the title.

template.scss
//Your Css Here
body{
    background: white;
}

#site-title{
    display: block;
    width: 100%;
    text-align: center;
    font-size: 2rem;
}

After saving my files, waiting for Sass to update the CSS, and reloading my webpage, this is what it looks like.

Your website should display the site title saved in your global configuration.

added title to siteBrowser preview with caching disabled

Add The Menu Module

The next item in my template is the menu module. This will span the entire width of the container.

index.php
<body class="site">

    <div class="container">
        <span id="site-title"><?php echo $sitename ?></span>

        <?php if ($this->countModules('menu')) : ?>
            <div class="navbar navbar-expand" id="top-menu">
                <jdoc:include type="modules" name="menu" style="none" />
            </div>

        <?php endif; ?>

    </div>

</body>

The menu code was added below the title. The line <?php if ($this->countModules('menu')) : ?> checks if the menu module is filled. If it's filled, it outputs the following html. Make sure you have a menu module published to the "menu" position in order to test this.

The next line starts the menu div, <div class="navbar navbar-expand" id="top-menu">

My template already has some layout overrides for the menu module to work a little better with Bootstrap's navbar. You can learn more about Bootstrap Nabvar options in their docs. I've used the classes navbar and navbar-expand from Bootstrap. This means this is going to be a navigation bar, and it's expanded (full width of container). I've given it the id of top-menu so I can easily add additional customizations within my template's scss file.

The line <jdoc:include type="modules" name="menu" style="none" /> is what adds the module in the "menu" position to the page. Additional module positions may be defined in the templateDetails.xml file, if you'd like. Note that the style attribute has to deal with mod_chromes (the styling templates for modules). To learn more about mod_chrome and add styles/headings to your modules, see the module chromes guide.

The <?php endif; ?> line ends the condition from before, where we checked if the menu module exists. This is the end of the menu module placement code. Any HTML after this line will be displayed, regardless of whether the menu module is filled.

I've added the following code to my template.scss file:

template.scss
#top-menu{
    background: #bcdeb1;
}

All this does is make the background of the menu the color I chose in the wireframe.

After saving both files, letting Sass watch the changes, and refreshing my browser, I now see a page that looks like this:

So now we have the site title and the menu down. We still have to do the left sidebar, the breadcrumbs, the main component area, and the footer.

added menu

The Grid

The easiest way to implement the layout with a left sidebar, breadcrumbs, and main content area will be to use the Bootstrap grid with columns.

By default, Bootstrap uses a 12 column/row layout. We can create columns in 1/12 increments. Each column belongs in a row. We can create columns in any increment of 1/12, so long as they add up to 12. For example, we could have a layout with two equal-width 6/12 columns in a row, or one smaller 4/12 column and one larger 8/12 column in a row, or three equal 4/12 columns in a row. Hopefully, you get the point.

Since I have a left sidebar, and it's smaller in width than the main component/breadcrumbs area, I'm going to put the left sidebar in a smaller column on the left, and the remaining two areas in a larger column on the right. The body of my index.php file now looks like this for the basic grid layout:

index.php
<body class="site">

    <div class="container">
        <span id="site-title"><?php echo $sitename ?></span>

        <?php if ($this->countModules('menu')) : ?>
            <div class="navbar navbar-expand" id="top-menu">
                <jdoc:include type="modules" name="menu" style="none" />
            </div>

        <?php endif; ?>

        <div class="row">
            <div class="col-3" id="left-sidebar">
                <!-- LEFT SIDEBAR CODE GOES HERE -->
            </div>
            <div class="col-9" id="main-area">
                <!-- RIGHT BREADCRUMBS AND COMPONENT GO HERE -->
            </div>
        </div>

    </div>

</body>

If you look at the code, I created a div with the "row" class functioning as the row. Within that row, I've created two separate divs. One is the left sidebar, with a width of 3 columns out of 12. The other is a larger column, with a width of 9 columns wide. So this will be a 1:3 layout with the left sidebar taking up 1/4 of the space and the remaining area taking up 3/4 of the space.

I've also added the ids left-sidebar and main-area for each column so we can easily target them with CSS.

To load the left sidebar, I'm going to use the same php snippet I used to insert the menu module. The difference is that this time, I'm going to use the position of "sidebar" instead of "menu". The sidebar position is already defined in joomstarter's templateDetails.xml file. I've skipped checking if the sidebar position is populated, for this example. So the <?php if ($this->countModules('sidebar')) : ?> is omitted. You don't have to check if a module position is populated, if you know something's going to be there.

index.php
<body class="site">

    <div class="container">
        <span id="site-title"><?php echo $sitename ?></span>

        <?php if ($this->countModules('menu')) : ?>
            <div class="navbar navbar-expand" id="top-menu">
                <jdoc:include type="modules" name="menu" style="none" />
            </div>

        <?php endif; ?>

        <div class="row">
            <div class="col-3" id="left-sidebar">
                <jdoc:include type="modules" name="sidebar" style="superBasicMod" />
            </div>
            <div class="col-9" id="main-area">
                <!-- RIGHT BREADCRUMBS AND COMPONENT GO HERE -->
            </div>
        </div>

    </div>

</body>

Finally, I added some CSS styling to template.scss for the left sidebar.

template.scss
#left-sidebar{
    background: #fac8c8;
    padding: 10px;
}

I published the login form in the "sidebar" position. Make sure anything you publish here is published to the "sidebar" position, not the "sidebar-right" or "sidebar-left" positions from the Cassiopeia template.

I set the style for the siderbar to the superBasicMod "module chrome" - this means it will load the module chrome/theme from this template/html/layouts/chromes/superBasicMod.php - this is what allows the title to be toggled on and off, along with other module-specific settings.

This is what my site looks like after everything's saved and refreshed:

added sidebarAdded sidebar

Wow! It's almost looking like a real template.

Moving on, let's add the breadcrumbs module and the component view to the right column.

This would also be a good place to add the "message" section. Joomla displays important messages here regarding user registration, errors, and so on.

index.php
<body class="site">

    <div class="container">
        <span id="site-title"><?php echo $sitename ?></span>

        <?php if ($this->countModules('menu')) : ?>
            <div class="navbar navbar-expand" id="top-menu">
                <jdoc:include type="modules" name="menu" style="none" />
            </div>

        <?php endif; ?>

        <div class="row">
            <div class="col-3" id="left-sidebar">
                <jdoc:include type="modules" name="sidebar" style="none" />
            </div>
            <div class="col-9" id="main-area">
                <div class="breadcrumbs">
                    <jdoc:include type="modules" name="breadcrumbs" style="none" />
                </div>
                <main>
					<jdoc:include type="message" />
                    <jdoc:include type="component" />
                </main>
            </div>
        </div>

    </div>

</body>

I've loaded the breadcrumbs module using the same method I loaded the menu and the sidebar module. The breadcrumbs module should be published to the breadcrumbs position by default, but set it to be there if it's somewhere else.

The line <jdoc:include type="component" /> is what loads the component view. This is where the bulk of your page's content should come from. It's where articles get displayed, categories get displayed, the registration page is displayed, etc. It's the main part of the page, which is why I put it in a <main> element.

The line <jdoc:include type="message" /> displays the message area.

I added two test articles to my website and featured them. Now, this is what my home page looks like:

main area done

The next area I have to make is the footer. I'm just going to make a basic footer. If you wanted to make a more complex footer, you could load a "footer" module down here. That is up to you. I've decided to just code the footer directly into the template, so it's simple and appears on all pages the same.

I've added this code at the end of my other row, within the same container.

index.php
        <div class="row">
            <div id="site-footer">
                <span>&copy; 2022 <?php echo $sitename ?> <span>
            </div>
        </div>

All it does is add another row below the last row for the footer. It displays the site's title along with a short copyright notice within a span element.

My added CSS looks like this:

template.scss
#site-footer{
    background: #6160ab;
    width: 100%;
    min-height: 100px;
    padding: 10px;
    color: white;
}

Hooray! My template's just about done. This is what it looks like with the footer.

template almost done with footer

The last thing I'd like to fix is the navbar at the top. It's part of the container, but because of the way Bootstrap styles things, its width doesn't match the width of the other elements. I'm going to fix this by putting it in its own div row.

        <div class="row">
            <?php if ($this->countModules('menu')) : ?>
                <div class="navbar navbar-expand" id="top-menu">
                    <jdoc:include type="modules" name="menu" style="none" />
                </div>

            <?php endif; ?>

        </div>

Completed index.php

<?php

/**
 * @package     Joomla.Site
 * @subpackage  Templates.joomstarter
 *
 * @copyright   (C) YEAR Your Name
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * This is a heavily stripped down/modified version of the default Cassiopeia template, designed to build new templates off of.
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

/** @var Joomla\CMS\Document\HtmlDocument $this */

$app = Factory::getApplication();
$wa  = $this->getWebAssetManager();

// Add Favicon from images folder
$this->addHeadLink(HTMLHelper::_('image', 'favicon.ico', '', [], true, 1), 'icon', 'rel', ['type' => 'image/x-icon']);


// Detecting Active Variables
$option   = $app->input->getCmd('option', '');
$view     = $app->input->getCmd('view', '');
$layout   = $app->input->getCmd('layout', '');
$task     = $app->input->getCmd('task', '');
$itemid   = $app->input->getCmd('Itemid', '');
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
$menu     = $app->getMenu()->getActive();
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';

//Get params from template styling
//If you want to add your own parameters you may do so in templateDetails.xml
$testparam =  $this->params->get('testparam');

//uncomment to see how this works on site... it just shows 1 or 0 depending on option selected in style config.
//You can use this style to get/set any param according to instructions at
//echo('the value of testparam is: '.$testparam);

// Get this template's path
$templatePath = 'templates/' . $this->template;

// Load bootstrap collapse
HTMLHelper::_('bootstrap.collapse');

//Register our web assets (Css/JS)
$wa->useStyle('template.joomstarter.mainstyles');
$wa->useScript('template.joomstarter.scripts');

//Set viewport
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');

?>
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">

<head>
    <jdoc:include type="metas" />
    <jdoc:include type="styles" />
    <jdoc:include type="scripts" />

</head>

<body class="site">

    <div class="container">
        <span id="site-title"><?php echo $sitename ?></span>

        <div class="row">
            <?php if ($this->countModules('menu')) : ?>
                <div class="navbar navbar-expand" id="top-menu">
                    <jdoc:include type="modules" name="menu" style="none" />
                </div>

            <?php endif; ?>

        </div>


        <div class="row">
            <div class="col-3" id="left-sidebar">
                <jdoc:include type="modules" name="sidebar" style="none" />
            </div>
            <div class="col-9" id="main-area">
                <div class="breadcrumbs">
                    <jdoc:include type="modules" name="breadcrumbs" style="none" />
                </div>
                <main>
                    <jdoc:include type="component" />
                </main>
            </div>
        </div>
        <div class="row">
            <div id="site-footer">
                <span>&copy; 2022 <?php echo $sitename ?> <span>
            </div>
        </div>

    </div>

</body>

</html>

Desktop Template Complete

The template's nearly done. Any additional style customizations are up to you.

template all done

Making it Responsive

The nice thing about grids and bootstrap is that they make it easy to create responsive grids. There are many viewport widths built into Bootstrap. One for smartphones, one for tablets, one for desktop, one for widescreen, etc. To learn more about responsive column sizing, I'd encourage you to read up on bootstrap columns.

I've decided I want to make my template responsive. On tablets and smaller, the columns will all be full-width. Then, on desktop (viewports size "lg" or bigger), they will take up the widths defined previously.

To do this, I just need to edit the classes of the columns. The first class, col-12, is the default column width. It's applied to any viewport. The next class, col-lg-#, defines how many columns the div takes up on desktop viewports and larger. So if I want to have a column that's full width on mobile, and 3 columns wide on desktop, I would set the class to be <div class="col-12 col-lg-3" >

The only area of my layout that actually uses multiple columns in one row is the area containing the sidebar, breadcrumbs, and main component. I want the left side and the right side to both be full-width on mobile devices. If multiple columns in the same row exceed the 12 column width limit, they will automatically wrap or stack on top of each other.

This is what the body of my index.php file looks like when changed to support mobile.

index.php
<body class="site">

    <div class="container">

        <span id="site-title"><?php echo $sitename ?></span>

        <div class="row">
            <?php if ($this->countModules('menu')) : ?>
                <div class="navbar navbar-expand" id="top-menu">
                    <jdoc:include type="modules" name="menu" style="none" />
                </div>

            <?php endif; ?>

        </div>

        <div class="row">
            <div class="col-12 col-lg-3" id="left-sidebar">
                <jdoc:include type="modules" name="sidebar" style="none" />
            </div>
            <div class="col-12 col-lg-9" id="main-area">
                <div class="breadcrumbs">
                    <jdoc:include type="modules" name="breadcrumbs" style="none" />
                </div>
                <main>
                    <jdoc:include type="component" />
                </main>
            </div>
        </div>
        
        <div class="row">
            <div id="site-footer">
                <span>&copy; 2022 <?php echo $sitename ?> <span>
            </div>
        </div>

    </div>

</body>

Note the classes used in <div class="col-12 col-lg-3" id="left-sidebar"> and <div class="col-12 col-lg-9" id="main-area"> in the above code.

When I resize my window, now the columns stack on smaller viewports. The left sidebar appears above the main content area. This way, they're not shrunken down to where the columns are too narrow for the screen.

desktop mobile

Final Notes on Template Development

There's still more to learn! But hopefully you now understand how to modify the template's style and layout. Again, if you're not familiar with Bootstrap, read up on it. I'm going to go over some more essential concepts below, related to packaging templates, and using parameters.

If you know how Javascript works and want to add additional interactive functionality to your template, you may edit template.js in thesite_root/media/templates/site/joomstarter/js directory.

If you'd like to learn more about creating new layouts for your components or modules, check out my guide on Joomla template overrides. This involves a bit more PHP knowledge and a deeper understanding of Joomla development.

 

Rebrand The Template

Now, let's examine custom branding. I will show you how to rename the files and give your template its own unique name. There are a few steps involved here.

Refactor The Files

Begin by coming up with a new name for your template. I'm going to name my template "Very Simple Template" or "verysimple" for short. You should have both a full template name and a short template/alias name in mind. For example, if you're naming your template "Blue Ridge Skies" that would be your full template name, but your short name might be "brs" or "blueridge". I'm going to refer to the shorter version as the template alias. Make sure it has no spaces or special characters in it.

You'll have to refactor, or rename every file and directory that has the word "joomstarter" in it. Replace "joomstarter" with your template alias, so I'll be replacing "joomstarter" with "verysimple". Then replace every instance of the word "joomstarter" with your alias in the code files themselves.

I'd encourage you to make a backup of all your template files in the various locations, or of your entire website, before proceeding.

You can do this manually, one file at a time. If your IDE supports refactoring/renaming, it might be easier.

If you're still running a ruby sass --watch, you need to close that console to rename the folder.

These are all the files and folders you must change to the alias:

  • site_root/templates/joomstarter folder
  • site_root/media/templates/site/joomstarter folder
  • site_root/language/en-GB/tpl_joomstarter.ini language file
  • site_root/language/en-GB/tpl_joomstarter.sys.ini language file

Now we have to change every instance of "joomstarter" to your template alias ("verysimple" in my case) in every bit of code where it exists.

If you're using Visual Studio Code, there's a feature that makes this easier. Open your entire Joomla site directory using the File Open Folder option. If you're using a different editor/IDE, you'll have to use their built in find/replace functions accordingly. I'm going to assume you're using VS Code for the rest of this.

Next, go to Edit Replace in Files

This will open a small area in the sidebar where you can find/replace strings of text. Enter "joomstarter" into search box, and your template alias into the replace box. Set both fields to match/preserve case. We want this to be case sensitive. In my example, I'm replacing "joomstarter" with "verysimple". Do not match the whole word. Parts of words are fine.

Hit enter and it will show you where it plans to make the replacements. Click the little replace all button to replace them all.

Repeat the same process, except this time, replace "joomstarter" with your alias, in caps. So "joomstarter" becomes "VERYSIMPLE" in my example. There should be about 26 results, unless you added something I didn't. This is mainly for the language files.

replace lowercase

Double check that all your folders, files, and instances of "joomstarter" in files has been renamed to the alias. If you did this correctly, your joomstarter template should now be broken. 😋

Custom Language Files

You may want to modify the language files stored at site_root/language/en-GB/tpl_yournewalias.sys.ini and site_root/language/en-GB/tpl_yournewalias.ini. These files contain the language fields for your full template name, its description, and any other text you want to show in template options. You can use spaces here. I've set mine to this:

VERYSIMPLE="Very Simple Template"

You may also want to change the XML_DESCRIPTION to be the description of your new template.

TPL_VERYSIMPLE_XML_DESCRIPTION="It's a very simple template I made to show people how templates work."

Note that the tpl_yournewalias.sys.ini file defines the template's name and description on the extension installer, and in the template manager/style manager. The tpl_yournewalias.ini file has the same fields for a name and an XML description. You should fill the name/description in within both language files. The tpl_yournewalias.ini file is used on the actual template style page itself.

After saving the language files, go to the site backend, Menu System Install Discover

The extension discovery tool "discovers" extensions that exist on your website in some form but haven't been installed, for whatever reason. Your newly renamed template should appear here along with whatever information you provided in the .sys language file. Select it and click the install button.

discover install new template

If you have renamed all the files and code correctly, you should now be able to see the renamed template under the template style manager. Set the newly renamed template to your default and make sure it still works. If it doesn't or you get an error installing, you probably missed renaming something.

 

Template Details

Now it's time to discuss a bit more about the templateDetails.xml file. This file contains several useful settings Joomla needs when it learns about our template. Open this file and look. You may want to make some modifications if you plan to redistribute your template to others.

The Basics

<extension type="template" client="site" method="upgrade">

This line tells Joomla that this extension is a template. It's a site template, not an admin template (it appears on the frontend). When you install the template, its method is "upgrade" so it will overwrite old template files with the new ones in the newly uploaded package. Change nothing about this line.

The next few xml attributes provide more details about the template. The name should be the template alias we set when we refactored the template files. The author can be your name.

It's up to you if you want to update the creationDate, author, authorEmail, and copyright attributes. You can just enter your info as plain text here.

	<name>verysimple</name>
	<version>1.00</version>
	<creationDate>June 2022</creationDate>
	<author>Kevin</author>
	<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
	<copyright>(C) 2022 Kevin</copyright>
	<description>TPL_VERYSIMPLE_XML_DESCRIPTION</description>
	<inheritable>1</inheritable>

The description is set to TPL_YOURTEMPLATE_XML_DESCRIPTION - this means it loads the XML_DESCRIPTION from the .sys language file under site_root/language/en-GB (or whatever language code you're using).

Inheritable means the template can be extended with additional child template styles. If you plan on reselling the template, you may want to leave this on. If you plan on having multiple template styles based off this template, leave this on. If you plan on only using one template for all the pages on your site (like I am on Kevins Guides) you can turn this off or remove this attribute.

Files and Folders

The files and media elements define where the files/folders are in your package, and where they get installed when the template is uploaded with the extension installer.

	<files>
		<filename>index.php</filename>
		<filename>joomla.asset.json</filename>
		<filename>templateDetails.xml</filename>
		<folder>html</folder>
	</files>
	<media destination="templates/site/verysimple" folder="media">
		<folder>js</folder>
		<folder>css</folder>
		<folder>scss</folder>
		<folder>images</folder>
	</media>

You can leave these as they are, unless you added additional files to the top template directory under site_root/templates/yourtemplate - any files in folders with the <folder> elements do not have to be defined individually. It will read all the files in that folder.

The media element has an attribute for destination and folder. The folder is where in the package Joomla is finding these files, and the destination is where they go (the template's media folder). You should leave these as they are, unless you structured your folders/files differently.

Module Positions

The next set of elements defines the module positions.

<positions>
		<position>header</position>
		<position>footer</position>
		<position>sidebar</position>
		<position>search</position>
		<position>breadcrumbs</position>
		<position>menu</position>
		<position>content-top</position>
	</positions>

These are the module positions we can add to our template using the <jdoc:include type="modules" name="modulename" style="none" /> code discussed earlier.

Note that we didn't use all these positions in the example template. You should only include the positions you actually use in the template.

The formal, or full names for the module positions are defined in the template's .sys.ini language file in the site_root/language folder.

Languages

The languages section tells Joomla where to find the language files and where to put them. It takes them from the "language" folder in the package and places them under the site_root/language/en-GB folder, in this example.

	<languages folder="language">
		<language tag="en-GB">en-GB/tpl_verysimple.ini</language>
		<language tag="en-GB">en-GB/tpl_verysimple.sys.ini</language>
	</languages>

Config

The config elements/attributes define option fields in the template style settings. I have a separate guide on this if you're interested in adding configurable options to your template.

 

Packaging The Template

Once you've renamed your template and set its details appropriately, you can prepare an installable package file for your template. This will enable other people to install the template on their websites, or allow you to install the template on your live public facing website.

Make sure you've extensively tested your template in multiple browsers (Edge, Firefox, and Chrome at the bare minimum. Safari if you've got a Mac). Make sure it works well on mobile, and that your site grid is responsive.

Creating The Archive

We need to pull files from multiple locations and then add them all to one compressed zip archive. Start by creating a new empty folder to contain the archive somewhere on your computer (like, on your desktop, for example).

Copy all the files and folders from site_root/templates/yourtemplate to the /new_package_folder.

Copy your modified language files site_root/language/en-GB/tpl_yourtemplate.ini and site_root/language/en-GB/tpl_yourtemplate.sys.ini into the new package under /new_package_folder/language/en-GB/.. Overwrite any existing files here with your modified versions.

Create a folder called "media" in the new package directory. Copy all your media folders from site_root/media/templates/site/yourtemplate to /new_package_folder/media.

Your new package folder should look something like this. I've omitted some of the optional files.


new_package_folder/
|-- html/
|   `-- mod_menu/
|-- language/
|   `-- en-GB/
|       |-- tpl_yourtemplate.ini
|       `-- tpl_yourtemplate.sys.ini
|-- media/
|   |-- css/
|   |   |-- template.min.css
|   |   `-- template.min.css.map
|   |-- images/
|   |   |-- favicon.ico
|   |   |-- template_preview.png
|   |   `-- template_thumbnail.png
|   |-- js/
|   |   `-- template.min.js
|   `-- scss/
|       |-- template.scss
|       `-- vendor/
|           `-- bootstrap/
|-- index.php
|-- joomla.asset.json
`-- templateDetails.xml
        

If you'd like, you may change the template_preview.png and template_thumbnail.png files to reflect screenshots of your new template. If you're not sharing this template with anyone, this step is unnecessary.

If any files defined in templateDetails.xml are not present in the proper locations in the package, the template cannot install.

Once you're pretty sure everything's where it's supposed to be, zip the entire new_package_folder directory, or whatever you called it.

zip it allCreate the archive

You should now have an installable package file. Upload it using the extension installer to any Joomla website to test it out. I'd recommend doing this in another test environment, if possible.

 

Conclusion

I'd encourage you to learn more about using Sass if you haven't done so already, and continue to review the Bootstrap 5 documentation.

If you liked this development guide, you might also be interested in my new guide on creating a Joomla 4 content plugin. It's just as detailed as this one!

While you're here, please check out my free 12-chapter long Intro to Joomla series! I'm always looking for comments and feedback for improvement.

Further Reading

  • Adding Custom Config Options - A guide on how to add custom configuration options to the template, so users can easily change the template.
  • Sass Basics - From Sass-lang.com - A brief introduction to Sass
  • Bootstrap 5 Docs - You should probably bookmark this. Make sure you understand how the grid system works. Then, I'd encourage you to read the sections on columns, buttons, cards, and anything else you think might be useful to add somewhere on your website. There's a lot of components available. 
  • Modifying Bootstrap Variables - How to customize Bootstrap to better suit the needs of your site using Sass and the _variables file
  • Custom Module Chromes - Create a set of styles or "chromes" to add borders or other styling effects around modules. Users can select a module style and it is applied automatically.
  • Override Layouts - Use template overrides to change the look and layouts of default Joomla components/pages. A custom login form, for example.
Write comments...
You are a guest ( Sign Up ? )
or post as a guest
Loading comment... The comment will be refreshed after 00:00.

Be the first to comment.

Related Guides

Adding Custom Options to your Joomla Template
Learn how to add and use custom fields in your template's style settings.
templateDetails.xml Overview
A quick overview of the templateDetails.xml file for Joomla templates.
Adding Custom Module Chrome (Styles)
How to create custom module chromes in your Joomla templates.
Creating Joomla Content Plugins (With Examples)
The ins and outs of basic content plugin development in Joomla 4.
Using Joomla's Web Asset Manager (joomla.asset.json)
Learn how to use Joomla's WebAssetManager
JoomCharta Free Joomla Template
A minimal, simple Bootstrap 5 template for Joomla 4.
Main Menu
Kevin's Guides
Full size image will appear here.