How do you create a SuiteP sub-theme in SuiteCRM 7?
A SuiteP sub-theme in SuiteCRM 7 is a folder at themes/SuiteP/css/<Name>/ with its own style.scss and compiled style.css. Copy Dawn's files, set Bootstrap variables before variables.scss and SuiteP variables after it, compile with Sass, register the name in custom/themes/SuiteP/themedef.php, then run Quick Repair and Rebuild.
Steps at a glance
- Copy Dawn. Copy themes/SuiteP/css/Dawn/ to themes/SuiteP/css/<YourName>/, choosing a name that is not Dawn, Day, Dusk, Night, Noon, Fonts or Bootstrap.
- Add two override files. Create _brand-pre.scss for Bootstrap variables and _brand-post.scss for SuiteP variables, and import them before and after variables.scss in style.scss.
- Set your colours. Put $navbar-bg, $sidebar-bg, $primary-btn-bg, $input-bg and the other SuiteP colour variables in _brand-post.scss.
- Compile to style.css. Run npx sass --style=compressed on style.scss to produce style.css in the same folder.
- Register the sub-theme. Create or extend custom/themes/SuiteP/themedef.php so it requires the core themedef and adds your name to the sub-theme options.
- Quick Repair and Rebuild. Run Admin > Repair > Quick Repair and Rebuild, then choose the sub-theme under Profile > Edit > Layout Options > Style.
What a SuiteP sub-theme is
Since SuiteCRM 7.10, the SuiteP theme ships as colour variants called sub-themes: Dawn, Day, Dusk and Night, with a fifth folder, Noon, present from 7.12. Each user picks one under Profile > Edit > Layout Options > Style. Adding your own puts your brand colours in that same list, without replacing or editing any stock file.
A sub-theme is just a folder of SCSS that compiles to one stylesheet. SuiteCRM serves the compiled style.css (through its cache/themes/SuiteP/css/<Name>/ copy) and never reads the .scss files at runtime, so whatever you change, you must recompile.
| File in themes/SuiteP/css/<Name>/ | What it does |
|---|---|
style.scss | Entry point. Imports the palette, variables, icons and the shared bootstrap and suitep-base partials |
style.css | The compiled result. The only file SuiteCRM serves |
color-palette.scss | The raw palette, $color-1 to $color-86 |
variables.scss | Bootstrap and SuiteP variables built from the palette |
icons.scss | Icon colours |
select.ico | The drop-down arrow image (absent from Dawn on 7.10 and 7.11, where SuiteP falls back to its own) |
The one rule that makes it work: override order
Most failed SuiteP themes compile cleanly and change nothing. The reason is how variables.scss declares things. Its Bootstrap variables are declared `!default`, which means "use this unless something already set it", so your value has to be set before the file is imported. SuiteP's own semantic variables, such as $navbar-bg, $sidebar-bg, $list-view-header-bg, $active-tab-bg and $primary-btn-bg, are plain assignments, so they overwrite anything set earlier and your value has to come after it.
The clean way to honour both is two small files and two extra imports in Dawn's style.scss:
@import "color-palette";
@import "brand-pre"; // Bootstrap variables: BEFORE variables.scss
@import "variables";
@import "brand-post"; // SuiteP variables: AFTER variables.scss
@import "icons";
// ...the rest of Dawn's imports, unchanged$navbar-bg: #1f3a5f;
$sidebar-bg: #f4f6f8;
$active-tab-bg: #1f3a5f;
$list-view-header-bg: #e8edf3;
$primary-btn-bg: #1f3a5f;
$input-bg: #ffffff;
$input-select-bg: #ffffff;Two stock defaults catch almost everyone. Dawn tints form inputs and selects mint ($input-bg and $input-select-bg), so a branded theme that does not override them keeps mint edit views. And SuiteP's primary, danger, success and info buttons all take their label colour from $default-btn-color, not from white, so changing a button background without checking that label can make it unreadable.
Compile the stylesheet
Any Dart Sass works. From the SuiteCRM root:
npx sass --style=compressed themes/SuiteP/css/<Name>/style.scss themes/SuiteP/css/<Name>/style.cssExpect a few hundred deprecation warnings about slash division: they come from SuiteP's own stock SCSS and are harmless. A compressed SuiteP stylesheet is around 545 KB.
Register it so it appears in the picker
SuiteCRM builds its theme list by scanning themes/ and then custom/themes/ for themedef.php. A custom themedef for SuiteP replaces the core one, so custom/themes/SuiteP/themedef.php must begin by requiring the core definition and then add your sub-theme to config_options.sub_themes.options. Those options are nested one level under a group label, and core only fills them when the LBL_SUBTHEMES language string is set, so code defensively:
<?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
global $app_strings;
// Start from the core definition: a custom themedef replaces it wholesale.
require dirname(__FILE__) . '/../../../themes/SuiteP/themedef.php';
if (!isset($themedef['config_options']['sub_themes']['options'])
|| !is_array($themedef['config_options']['sub_themes']['options'])) {
$themedef['config_options']['sub_themes']['options'] = array();
}
$opts = &$themedef['config_options']['sub_themes']['options'];
$group = key($opts);
if ($group === null) {
$group = !empty($app_strings['LBL_SUBTHEMES']) ? $app_strings['LBL_SUBTHEMES'] : 'Sub-themes';
$opts[$group] = array();
}
$opts[$group]['Acme'] = 'Acme';If the file already exists (another add-on may have registered a sub-theme), add your lines to it rather than replacing it. Then run Admin > Repair > Quick Repair and Rebuild so the theme registry and compiled-CSS cache are rebuilt.
Make it the default for everyone
Which sub-theme a user sees is decided in this order: their own subtheme preference, then the site default in $sugar_config['theme_settings']['SuiteP']['sub_themes'], then Dawn. There is no admin screen for it: Admin > Themes only chooses the theme, and the SuiteP settings page it links to shows the sidebar option but no sub-theme picker (checked on SuiteCRM 7.15.2). Set the site default in config_override.php:
$sugar_config['theme_settings']['SuiteP']['sub_themes'] = 'Acme';Users who already chose a sub-theme keep their choice until it is changed for them. Be careful scripting that: on SuiteCRM 7.14 and 7.15, calling setPreference() for a user other than the one logged in can overwrite that user's whole preference row, including timezone, date format and currency.
Names you cannot use
Dawn,Day,Dusk,NightandNoon: the stock sub-themes.FontsandBootstrap: real folders insidethemes/SuiteP/css/. Windows and macOS file systems ignore case, so a sub-theme with either name collides with them.
Packaging it for Module Loader
Copying files by hand works for one server. To install through Admin > Module Loader, three manifest details matter, and each has caught out experienced developers:
- Set
'type' => 'module', not'theme'. A theme-type package is copied raw and never runs ModuleInstaller, so no install script runs and nothing is recorded for uninstall. acceptable_sugar_versionsis checked against$sugar_version, which is6.5.25on every SuiteCRM 7 and 8. Put a 7.x pattern there and the package can never install. Useacceptable_suitecrm_versions(7.12 and later) for the real version check.- Do not name your scripts
scripts/pre_install.php,post_install.php,pre_uninstall.phporpost_uninstall.phpunless they define the matching function: the upgrade wizard includes those paths a second time and calls a function of that name.
And tell whoever installs it: Disable does not switch a theme off. SuiteCRM has no disable hook and does not delete copied files on Disable, so users keep seeing the theme. Uninstall is the off switch. The install guide covers the full Module Loader flow.
The shortcut
Brandtint builds exactly this package from a logo, for the precise SuiteCRM 7 version you run: the sub-theme folder with the overrides on the correct side of variables.scss, a themedef merge that leaves other sub-themes alone, install and uninstall scripts that restore every user's previous choice, and every text and background pair checked for contrast. Preview it free; pay only to download.
Questions
Where are SuiteCRM 7 sub-theme files stored?
In themes/SuiteP/css/<Name>/, alongside the stock Dawn, Day, Dusk and Night folders. The registration that makes it appear in the picker goes in custom/themes/SuiteP/themedef.php.
Why do my SuiteP variable changes have no effect?
Usually because they are on the wrong side of variables.scss. Bootstrap variables there are !default and must be set before it is imported; SuiteP variables such as $navbar-bg are plain assignments and must be set after it. Also remember SuiteCRM serves only the compiled style.css, so recompile and run Quick Repair and Rebuild after every change.
Does a SuiteP sub-theme work on SuiteCRM 7.10 and 7.11?
Yes. Sub-themes arrived in 7.10. Two differences: Dawn has no select.ico on 7.10 and 7.11, and Module Loader there does not support acceptable_suitecrm_versions, so a version check has to run in a pre-install script instead.
How do I remove a custom sub-theme?
If it was installed as a package, use Uninstall in Module Loader (Disable leaves it active). If you added it by hand, delete its folder and its lines in custom/themes/SuiteP/themedef.php, reset anyone using it, and run Quick Repair and Rebuild.
About the author
Muhammad Ilyas builds Brandtint at Techholds, including the SuiteCRM 7 and SuiteCRM 8 theme packages these guides are written from. Muhammad Ilyas on LinkedIn