Joomla Custom Template Development
A Joomla template determines site appearance: HTML markup, CSS, JavaScript inclusion. Joomla 5 uses Cassiopeia as base template — you can create a child template or develop from scratch.
Template Structure
templates/my-template/
├── index.php # Main template file
├── templateDetails.xml # Manifest (required)
├── component.php # Component template (print version)
├── error.php # Error page
├── offline.php # Maintenance page
├── css/
│ ├── template.css
│ └── custom.css
├── js/
│ └── template.js
├── images/
│ └── logo.svg
├── html/ # Component layout overrides
│ ├── com_content/
│ │ └── article/
│ │ └── default.php
│ └── layouts/
│ └── joomla/
└── language/
└── en-GB/
templateDetails.xml
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="template" client="site">
<name>my-template</name>
<author>Your Company</author>
<version>1.0.0</version>
<description>Custom template</description>
<files>
<filename>index.php</filename>
<filename>templateDetails.xml</filename>
<folder>css</folder>
<folder>js</folder>
<folder>images</folder>
<folder>html</folder>
</files>
<positions>
<position>header</position>
<position>banner</position>
<position>top-a</position>
<position>top-b</position>
<position>main-top</position>
<position>sidebar-left</position>
<position>sidebar-right</position>
<position>main-bottom</position>
<position>footer</position>
</positions>
<config>
<fields name="params">
<fieldset name="basic">
<field name="logo" type="media" label="Logo" />
<field name="accent_color" type="color" label="Accent Color" default="#0066cc" />
<field name="show_backtotop" type="radio" label="Back to Top Button"
default="1">
<option value="1">Yes</option>
<option value="0">No</option>
</field>
</fieldset>
</fields>
</config>
</extension>
index.php: Main File
<?php defined('_JEXEC') or die; ?>
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<?php
// Include template CSS
$wa = $this->getWebAssetManager();
$wa->registerAndUseStyle('template.my-template', 'css/template.css');
$wa->registerAndUseScript('template.my-template', 'js/template.js', [], ['defer' => true]);
?>
</head>
<body class="site <?php echo $this->params->get('pageclass_sfx', ''); ?>">
<header class="site-header">
<?php if ($this->params->get('logo')) : ?>
<a href="<?php echo $this->baseurl; ?>" class="site-logo">
<img src="<?php echo HTMLHelper::_('image', $this->params->get('logo'), '', [], true, 1); ?>"
alt="<?php echo $sitename; ?>" loading="eager">
</a>
<?php endif; ?>
<nav class="site-nav">
<jdoc:include type="modules" name="header" style="none" />
</nav>
</header>
<div class="site-wrapper">
<?php if ($this->countModules('sidebar-left')) : ?>
<aside class="sidebar sidebar--left">
<jdoc:include type="modules" name="sidebar-left" style="xhtml" />
</aside>
<?php endif; ?>
<main class="site-content" id="main-content">
<jdoc:include type="message" />
<jdoc:include type="component" />
</main>
<?php if ($this->countModules('sidebar-right')) : ?>
<aside class="sidebar sidebar--right">
<jdoc:include type="modules" name="sidebar-right" style="xhtml" />
</aside>
<?php endif; ?>
</div>
<footer class="site-footer">
<jdoc:include type="modules" name="footer" style="none" />
<p>© <?php echo date('Y'); ?> <?php echo $sitename; ?></p>
</footer>
<jdoc:include type="scripts" />
</body>
</html>
Component Layout Override
Copy original layout to template html/ folder:
components/com_content/tmpl/article/default.php
→
templates/my-template/html/com_content/article/default.php
Joomla automatically uses template version. Modify article markup without touching core files.
Child Template
Joomla 4+ supports child templates:
<!-- Child template templateDetails.xml -->
<inheritable>0</inheritable>
<parent>cassiopeia</parent>
Child template inherits all parent files, overrides only what's needed. Parent updates apply automatically.
Build with Vite
// vite.config.js
export default {
build: {
outDir: 'templates/my-template',
rollupOptions: {
input: { main: 'src/js/main.js' },
output: { assetFileNames: 'css/[name].[ext]', entryFileNames: 'js/[name].js' }
}
}
};
Timeline
Custom template development from finished design with 8–12 module positions — 5–10 days.







