1. Theme Structure
Themes reside in the /theme directory. Most modern themes inherit from boost (Bootstrap 4/5 based).
// config.php
$THEME->name = 'mytheme';
$THEME->parents = ['boost']; // Inherit from Boost
$THEME->sheets = ['custom']; // Load custom.css
$THEME->enable_dock = false;
2. Mustache Templates
Moodle uses Mustache for templating. Override core templates by placing them in /theme/mytheme/templates/.
{{! theme/mytheme/templates/core/frontpage.mustache }}
<div class="my-custom-frontpage">
<h1>{{sitename}}</h1>
{{{ output.main_content }}}
</div>
3. SCSS Compilation
Moodle compiles SCSS on the fly. Define your SCSS variables and imports in /theme/mytheme/scss/.
4. Renderers
Renderers are PHP classes that generate HTML. You can override any core renderer in your theme.
// theme/mytheme/renderers.php
class theme_mytheme_core_renderer extends core_renderer {
public function login_info() {
return '<div class="custom-login">Login Here</div>';
}
}
5. AMD Modules (JavaScript)
Moodle uses RequireJS (AMD) for modular JavaScript. Place your JS in amd/src/.
// amd/src/myscript.js
define(['jquery', 'core/modal'], function($, Modal) {
return {
init: function() {
$('button').click(function() {
Modal.create({ title: 'Hello', body: 'World' });
});
}
};
});
Call it from PHP:
$PAGE->requires->js_call_amd('theme_mytheme/myscript', 'init');
6. Theme Settings
Themes can have their own settings page in Site Administration. Define them in settings.php.
// theme/mytheme/settings.php
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
$settings = new theme_boost_admin_settingspage_tabs('themesettingmytheme', get_string('configtitle', 'theme_mytheme'));
$page = new admin_settingpage('theme_mytheme_general', get_string('generalsettings', 'theme_mytheme'));
// Add a logo upload setting
$name = 'theme_mytheme/logo';
$title = get_string('logo', 'theme_mytheme');
$description = get_string('logodesc', 'theme_mytheme');
$setting = new admin_setting_configstoredfile($name, $title, $description, 'logo');
$setting->set_updatedcallback('theme_reset_all_caches');
$page->add($setting);
$settings->add($page);
$ADMIN->add('themes', $settings);
}
7. Layout Files
Layout files define the HTML structure of the page (header, footer, blocks). They are located in theme/mytheme/layout/.
Common layouts include:
- columns2.php: Standard page with side blocks.
- login.php: The login page.
- frontpage.php: The site home.
// theme/mytheme/layout/columns2.php
echo $OUTPUT->doctype();
?>
<html htmlattributes(); ?>>
<head>
standard_head_html(); ?>
</head>
<body body_attributes(); ?>>
standard_top_of_body_html(); ?>
<header>render_from_template('theme_mytheme/navbar', []); ?></header>
<div id="page" class="container-fluid">
<div id="page-content" class="row">
<div id="region-main-box" class="col-12">
main_content(); ?>
</div>
</div>
</div>
standard_end_of_body_html(); ?>
</body>
</html>
8. Core JavaScript Libraries
Moodle provides powerful core AMD modules to handle common tasks.
AJAX Calls
define(['core/ajax', 'core/notification'], function(Ajax, Notification) {
var promises = Ajax.call([{
methodname: 'local_myplugin_get_items',
args: { courseid: 123 }
}]);
promises[0].done(function(response) {
console.log(response);
}).fail(Notification.exception);
});
Language Strings in JS
define(['core/str'], function(Str) {
Str.get_strings([
{ key: 'yes', component: 'core' },
{ key: 'no', component: 'core' }
]).done(function(strings) {
console.log(strings[0]); // "Yes"
});
});