October CMS 3.3 - Dark Mode Release

Release Note 34

Version 3.3 of October CMS contains introduces additional styling options to the admin panel along with white-labelling.

Table of Contents

New Backend Customization Options

You can now attach a corporate logo to the Customize Backend settings area, that includes a full sized logo in the top navigation bar. When a navigation logo is supplied, it will appear in a fixed position, and the dashboard link is replaced by the logo. A dashboard icon is also available for collapsed and left-side menu modes, which can also be used by itself for a cleaner look.


A new Colors tab has also been added that includes color modes (Light, Dark, Automatic) and various color presets. It is also possible to specify a custom palette of colours for both dark and light modes.

You can include your own palette presets by extending the backend.brand.getPalettePresets event. The format of the $presets variable can be found in the Backend\Models\BrandSetting\HasPalettes class

Event::listen('backend.brand.getPalettePresets', function(&$presets) {

New configuration has been added to the config/backend.php under the brand value to hard-code the default branding settings.

'brand' => [
    'enabled' => false,
    // ...
    'menu_logo_path' => '~/app/assets/images/menu_logo.png',
    'dashboard_icon_path' => '~/app/assets/images/dashboard_icon.png',
    // ...

Inverse Tailor Relations

The entries field now has added support for inverse relationships. The specification involves adding an inverse property to the field definition and supplying the name of the other relation. For example, if a Post blueprint has a categories relation.

    type: entries
    source: Blog\Category

The inverse Category blueprint must know about the above field and specify it for the inverse property. For example, the following makes the posts inverse relation available.

    type: entries
    source: Blog\Post
    inverse: categories
    hidden: true

The name of the inverse field is needed to determine the relationship type going in the other direction. See the Entries Content Field documentation as a reference for this feature.

Multisite Setting Models

There is a new System\Models\SettingModel base class that introduces support for the Multisite trait. It requires retrofitting older code to extend a base class instead of implementing a behavior. The new base class is a drop-in replacement with an identical interface and better performance.

Old code that is still supported (deprecated soon).

use Model;

class Setting extends Model
    public $implement = [

Newer code that supports multisite (drop-in replacement).

use System\Models\SettingModel;

class Setting extends SettingModel

Color Picker Improvements

Alpha channel support is now included with the showAlpha property, and when set to true will produce an 8-digit hex code. The first six characters represent the RGB (red, green, blue) value of the color, the last two represent the alpha chanel of the color.

    label: Background
    type: colorpicker
    showAlpha: true

The color picker has added a feature for displaying a grouped input next to the color picker using the showInput property. This mode will disable the available colors and make choosing and entering a custom hex color the primary focus.

    label: Primary Color
    type: colorpicker
    showInput: true

Extending List Filter Updates

You may now extend the AJAX update partials when a list filter changes using the listExtendRefreshResults controller override method. This lets you update toolbars, charts and other partials based on the updated results.

public function listExtendRefreshResults($list, $result)
    // Get the value of the status code filter scope
    $statusCode = $this->listGetFilterWidget()->getScope('status_code')->value;

    // Include dynamic bulk actions with the update
    return ['#list-bulk-actions' => $this->makePartial('list_bulk_actions', [
        'currentStatus' => $statusCode

Updated AJAX Exception Policy

From v3.3, when debug mode is off, throwing generic exceptions in AJAX will display a generic message. Safe exception types such as ApplicationException and ValidationException (allow-list) will display their error message to the user, and should never expose sensitive information.

Enabling the configuration cms.exception_policy_v1 will keep the old logic that shows all generic exception messages, except for some that are known to contain sensitive information (block-list). We recommend using this setting only when code cannot be updated to transform exceptions to safe ones.

'exception_policy_v1' => env('CMS_EXCEPTION_POLICY_V1', false),

Additionally, an exception can be declared safe by defining a getSafeMessage method on the exception class.

public function getSafeMessage()
    return $this->message;

Notable Minor Changes

Validating Related Attributes

When validating your models, you may now validate the attributes of relations, including those found in deferred records. Deferred records are now included in existence checks.

List Structure Permissions

It is now possible to apply a permission to prevent modification of list structures. When a permissions property is defined, only users with that permission can reorder the records.

New Dashboard Permissions

The dashboard section has new permissions added to users and roles:

  • Create Widgets: Allows adding and removing widgets (includes reordering)
  • Manage Widgets: Allows configuration of widgets (includes reordering)

Disable Mail Settings

A new configuration item backend.force_mail_setting has been added to disable the mail setting screen found in the backend. Set to true to prevent any user from modifying the mailer settings via the administration panel and always use the file-based configuration found in config/mail.php.

Not Equal to Date Filter

The date filter widget type now includes a notEquals condition that can be used to filter records not within the selected date from start to end of day.

This is the end of the document, you may read the announcement blog post or visit the changelog for more information.

comments powered by Disqus