Moodle has a great documentation page for creating a theme based on Boost theme but that one is for Moodle 3.2 and it does not work for 4.x versions.

I had to create a child theme recently, so now I have the steps for a tutorial for the 4.x versions.

Getting started

The tutorial is based on the Moodle documentation, however, there are many differences between the old 3.x Boost theme and 4.x Boost theme.

Choose a name

The theme I made was for a company so, I picked the name of the company, but here I will call it eduroll.

Starting files

Theme is a plugin, themes must start with the basic structure of a plugin in Moodle. The new documentation for an overview of the files common to all plugins in Moodle can be found here.

Let’s start creating our theme. First, create the folder for the new theme under “/theme/” folder in the Moodle root directory.

/theme/eduroll

Now add the first standard plugin files to the theme which is the version.php.

<?php
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.

// This line protects the file from being accessed by a URL directly.                                                               
defined('MOODLE_INTERNAL') || die();                                                                                                
                                                                                                                                    
// This is the version of the plugin.                                                                                               
$plugin->version = '2023042400';                                                                                                    
                                                                                                                                    
// This is the version of Moodle this plugin requires (this one is for 4.2).                                                                              
$plugin->requires = '2023041800';                                                                                                   
                                                                                                                                    
// This is the component name of the plugin - it always starts with 'theme_'                                                        
// for themes and should be the same as the name of the folder.                                                                     
$plugin->component = 'theme_eduroll';                                                                                                 
                                                                                                                                    
// This is a list of plugins, this plugin depends on (and their versions). Here we depend on the Moodle 4.2 Boost theme.                                                         
$plugin->dependencies = [                                                                                                           
    'theme_boost' => '2023042400'                                                                                                   
];

We need a language file. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. You can copy the lang file of the Boost theme and update the following strings or just create one like this:
/theme/photo/lang/en/theme_eduroll.php

<?php
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.

// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();                                                                                                
                                                                                 
$string['choosereadme'] = 'Theme Eduroll is a child theme of Boost.';
// The name of our plugin.                                                                                                    
$string['pluginname'] = 'Eduroll';
// The title of the config settings.
$string['configtitle'] = 'Eduroll';
// The privacy metadata
$string['privacy:metadata'] = 'The Eduroll theme does not store any personal data about any user.';

Theme specific files

Themes require a lib.php file. The Moodle documentation says that this file can be empty. I wanted to brand the new theme, therefore I wanted to add my own SCSS. I copied the default.scss and the plain.scss files of the Boost theme to the /theme/eduroll/scss/preset/ directory and my own SCSS to the /theme/eduroll/scss/ directory.
In another post, I will explain how to do branding.
In this lib file, I have a function which loads the default SCSS and adds my SCSS to it. This function will be called from the config.
There can be other options for the branding.

lib.php

<?php

// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();

/**
 * Returns the SCSS content.
 *
 * @param theme_config $theme The theme config object.
 * @return string
 */
function theme_eduroll_get_main_scss_content($theme) {
    global $CFG;

    $scss = '';
    $filename = !empty($theme->settings->preset) ? $theme->settings->preset : null;
    $fs = get_file_storage();
// Here we loads the Boost's default SCSS files.
    $context = context_system::instance();
    if ($filename == 'default.scss') {
        $scss .= file_get_contents($CFG->dirroot . '/theme/eduroll/scss/preset/default.scss');
    } else if ($filename == 'plain.scss') {
        $scss .= file_get_contents($CFG->dirroot . '/theme/eduroll/scss/preset/plain.scss');
    } else if ($filename && ($presetfile = $fs->get_file($context->id, 'theme_eduroll', 'preset', 0, '/', $filename))) {
        $scss .= $presetfile->get_content();
    } else {
        // Safety fallback - maybe new installs etc.
        $scss .= file_get_contents($CFG->dirroot . '/theme/boost/scss/preset/default.scss');
    }
// And adding my own SCSS	
	$scss .= file_get_contents($CFG->dirroot . '/theme/eduroll/scss/eduroll.scss');

    return $scss;
}

Theme config goes in a config.php file. This is one of the most important files in the theme. There are many changes from the 3.2 version. You can see them with comments below.
config.php

<?php

// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.

// This line protects the file from being accessed by a URL directly.                                                               
defined('MOODLE_INTERNAL') || die();

// The first setting we need is the name of the theme. Must be the same as the directory
$THEME->name = 'eduroll';

// This setting list the style sheets we want to include in our theme. That can also work, but I had to change the SCSS variables, do I had to use the "Boost" way.
$THEME->sheets = [];

// No use of editor sheets but better to add here
$THEME->editor_sheets = [];

// Here we load the main SCSS content
$THEME->scss = function($theme) {
    return theme_eduroll_get_main_scss_content($theme);
};

// Tell Moodle to use Boost theme as the parent theme
$THEME->parents = ['boost'];

// These had to be added (same as in Boost)
$THEME->requiredblocks = '';
$THEME->precompiledcsscallback = 'theme_boost_get_precompiled_css';

$THEME->iconsystem = \core\output\icon_system::FONTAWESOME;

$THEME->haseditswitch = true;
$THEME->yuicssmodules = array();
$THEME->usescourseindex = true;
$THEME->usefallback = true;
$THEME->rendererfactory = 'theme_overridden_renderer_factory';

// By default, all boost theme do not need their titles displayed.
$THEME->activityheaderconfig = [
    'notitle' => true
];

Need to copy the Boost settings page so different settings can be added later.
settings.php

<?php

defined('MOODLE_INTERNAL') || die();

if ($ADMIN->fulltree) {
    // Use Boosts code for the settings tab
    $settings = new theme_boost_admin_settingspage_tabs('themesettingeduroll', get_string('configtitle', 'theme_eduroll'));
    $page = new admin_settingpage('theme_eduroll_general', get_string('generalsettings', 'theme_eduroll'));

    // Unaddable blocks.
    // Blocks to be excluded when this theme is enabled in the "Add a block" list: Administration, Navigation, Courses and
    // Section links.
    $default = 'navigation,settings,course_list,section_links';
    $setting = new admin_setting_configtext('theme_eduroll/unaddableblocks',
        get_string('unaddableblocks', 'theme_eduroll'), get_string('unaddableblocks_desc', 'theme_eduroll'), $default, PARAM_TEXT);
    $page->add($setting);

    // Preset.
    $name = 'theme_eduroll/preset';
    $title = get_string('preset', 'theme_eduroll');
    $description = get_string('preset_desc', 'theme_eduroll');
    $default = 'default.scss';

    $context = context_system::instance();
    $fs = get_file_storage();
    $files = $fs->get_area_files($context->id, 'theme_eduroll', 'preset', 0, 'itemid, filepath, filename', false);

    $choices = [];
    foreach ($files as $file) {
        $choices[$file->get_filename()] = $file->get_filename();
    }
    // These are the built in presets.
    $choices['default.scss'] = 'default.scss';
    $choices['plain.scss'] = 'plain.scss';

    $setting = new admin_setting_configthemepreset($name, $title, $description, $default, $choices, 'eduroll');
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    // Preset files setting.
    $name = 'theme_eduroll/presetfiles';
    $title = get_string('presetfiles','theme_eduroll');
    $description = get_string('presetfiles_desc', 'theme_eduroll');

    $setting = new admin_setting_configstoredfile($name, $title, $description, 'preset', 0,
        array('maxfiles' => 20, 'accepted_types' => array('.scss')));
    $page->add($setting);

    // Background image setting.
    $name = 'theme_eduroll/backgroundimage';
    $title = get_string('backgroundimage', 'theme_eduroll');
    $description = get_string('backgroundimage_desc', 'theme_eduroll');
    $setting = new admin_setting_configstoredfile($name, $title, $description, 'backgroundimage');
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    // Login Background image setting.
    $name = 'theme_eduroll/loginbackgroundimage';
    $title = get_string('loginbackgroundimage', 'theme_eduroll');
    $description = get_string('loginbackgroundimage_desc', 'theme_eduroll');
    $setting = new admin_setting_configstoredfile($name, $title, $description, 'loginbackgroundimage');
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    // We use an empty default value because the default colour should come from the preset.
    $name = 'theme_eduroll/brandcolor';
    $title = get_string('brandcolor', 'theme_eduroll');
    $description = get_string('brandcolor_desc', 'theme_eduroll');
    $setting = new admin_setting_configcolourpicker($name, $title, $description, '');
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    // Must add the page after definiting all the settings!
    $settings->add($page);

    // Advanced settings.
    $page = new admin_settingpage('theme_eduroll_advanced', get_string('advancedsettings', 'theme_eduroll'));

    // Raw SCSS to include before the content.
    $setting = new admin_setting_scsscode('theme_eduroll/scsspre',
        get_string('rawscsspre', 'theme_eduroll'), get_string('rawscsspre_desc', 'theme_eduroll'), '', PARAM_RAW);
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    // Raw SCSS to include after the content.
    $setting = new admin_setting_scsscode('theme_eduroll/scss', get_string('rawscss', 'theme_eduroll'),
        get_string('rawscss_desc', 'theme_eduroll'), '', PARAM_RAW);
    $setting->set_updatedcallback('theme_reset_all_caches');
    $page->add($setting);

    $settings->add($page);
}

Ready to go!

We are done.
Again, this is not the minimum install of a child theme. A bit more so you can start to customize it.
And here are all the files:

.
│   config.php
│   lib.php
│   settings.php
│   version.php
│
├───lang
│   └───en
│           theme_eduroll.php
│
└───scss
    │   eduroll.scss
    │
    └───preset
            default.scss
            plain.scss

Enjoy.
Cheers,

Leave a comment

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.