- Created by: Krisztian Pinter
- Created in: 2020.
- Updated on: 2026.04.08.
- Introduction
- What will you need to work with this theme?
- Theme installation
- Theme overview
- Third party libraries
- Working with this theme (commands)
BRAINSUM starterkit is a modern, responsive, mobile-first Drupal 11 starterkit. It doesn't use any base theme but inspired by Olivero, the default core frontend theme.
Every part of this theme follows the Drupal standards, so it's fully component-based (libraries), and compatible 100% with ES6, SMACSS, ITCSS, and BEMit.
For building css and javascript we use DDEV, yarn and native node.js commands.
In this version of the starterkit the Shake.sass was also incorporated witch is a ITCSS- and BEMit-based Sass-only framework.
- Installed DDEV
- Installed Drupal 11 with DDEV
- Set asset-packagist to composer.json of Drupal
Note: the required node.js version will be set by the install process.
ddev add-on get ddev/ddev-browsersyncClone this theme to /themes/contrib.
cd themes/contrib
git clone https://github.com/keeteean/brainsum_starterkit.gitCD to the web
directory then run the theme generate command:
ddev php ./web/core/scripts/drupal generate-theme --starterkit brainsum_starterkit [your_theme] --path themes/customThis will generate a new theme named your_theme to the /themes/custom
directory and add extra DDEV config files.
You can remove the BRAINSUM Starterkit theme now.
ddev buildcd themes/custom/[your_theme]/
ddev yarn installSet code quality tools in your code editor / IDE (all config files are in the theme's root):
- StyleLint
- ESlint
- Prettier
- CSS Var Complete
After installed the corresponding extensions, put these lines to your user/workspace config file:
"editor.formatOnPaste": true,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"eslint.format.enable": true,
"eslint.ignoreUntitled": true,
"eslint.packageManager": "yarn",
"eslint.validate": [
"javascript",
"typescript",
"json",
],
"stylelint.packageManager": "yarn",
"stylelint.customSyntax": "postcss-scss",
"stylelint.validate": [
"css",
"less",
"postcss",
"scss"
],
"stylelint.snippet": [
"css",
"less",
"postcss",
"scss"
],
"[css]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},Checkout all extensions can find their config file. Example put these lines to the workspace config file:
"stylelint.configBasedir": "web/themes/custom/your_theme",
"stylelint.configFile": "web/themes/custom/your_theme/.stylelintrc.json",
"prettier.configPath": "web/themes/custom/your_theme/.prettierrc",Some modules are optional and can be removed if not needed. These modules even
provide settings that can be adjusted in the related settings yaml files:
settings/*.settings.yml.
- Forms:
settings/forms.settings.ymlSee Forms readme. - Header:
settings/header.settings.yml - Layout:
settings/layout.settings.yml - Pager:
settings/pager.settings.yml - Tabledrag:
settings/tabledrag.settings.yml - Tables:
settings/tables.settings.yml
*For the forms module, you may need to install additional libraries. See the Bundled libraries into this theme section below.
To generate CSS files, we use Sass. You can find all source Sass files in the
src/sass/ directory. We organize all Sass files according to ITCSS and
SMACSS, such as:
- settings: we store all global variables here,
- tools: all global functions, mixins,
- base: CSS reset, collecting all CSS custom properties and theming HTML elements,
- objects: layout and non-content related very generic items,
- components: all content-related items,
- utilities: class-based global tools (pls, prefer classes over mixins),
- pages: page specific theming rules, avoid to use them, use components whenever you can
Because we have use Drupal libraries, we generate CSS files from the most Sass files. If you create a new Sass file, don't forget to add the generated SMACSS categorized CSS to the appropriated library.
Because we use modular SASS, we can't use @import to import Sass files. You'll
need to use @use instead. See in the
official documentation.
The main difference between @import and @use is that you can't access all
variables, mixins and functions globally. If you want to use one of them, first
you have to import via @use - with an optional namespace - the Sass file where
it is defined. To make it easier there are two main importer files in the SASS
root: _settings.scss and _tools.scss.
You can import all SASS variables via @use "../settings";. And you can use all
global variables from the 1.settings folder with the settings namespace, like:
settings.$variable-name. For example: settings.$prefers-reduced-motion.
Similarly, you can import all mixins and functions via @use "../tools"; from
the 2.tools folder with the tools namespace, like: tools.mixin-name().
For example: @include tools.breakpoint(medium, settings.$max-width) {}.
We use CSS custom properties for theme variables except for the ones that are
used in SASS control structures like @if, @for, @each, etc.
All global CSS custom properties are defined in the 1.settings/ layer, inside
:root{} blocks. For all local CSS custom properties, place the new (or the
same ones to override their default values) variables inside component classes.
like: .c-message--warning { --color-text-primary: #ebb504; }.
Whenever is possible, please use vanilla CSS instead of SASS. SASS should only be used when it provides a clear advantage over vanilla CSS. So if there is a css and sass version of the same thing, use the css version. For example, for 50% lighter color shade, use:
color: hsl(from var(--color-primary) h s l / 50%);instead of:
@use "sass:color";
color: color.scale($color-primary, $lightness: 50%);For the better exotic language support (RTL and Asian languages) we use and
required to use logical properties instead of physical properties. For example:
use margin-inline-start instead of margin-left.
There is a Stylelint plugin to warn and correct you if you use physical
properties (except float). If you don't want to use it, you can disable it in
the .stylelintrc.json file: csstools/use-logical.
Breakpoints are defined using the CSS Custom Media Queries
specification in src/sass/1.settings/_settings.breakpoints.css. While this
feature is in working draft state, we should use PostCSS to process it.
This settings file uses the @custom-media syntax processed by PostCSS's
postcss-custom-media plugin, which transforms custom media queries into
standard media queries during build.
The file is pure CSS (not SCSS) because these breakpoints need to be globally available across all compiled CSS files. This ensures consistent breakpoint usage throughout the entire project without Sass variable scope limitations.
Whenever possible, use inline SVGs instead of <img> tag or background images.
For inlining SVG icons, you can use the Icon SDC
(components/icon). For example:
{{ include('brainsum_starterkit:icon', {
icon: 'angle-down-solid',
size: 16,
class: 'c-menu__toggle-icon',
alt: 'Down angle'|t,
}) }}If it's not possible (e.g. <input> element), you can also inline SVG icons
into CSS via postcss-inline-svg
plugin. For example place the colorable* SVG icon into the images/icons
directory, then:
.checkmark {
background: svg-load("../../../images/icons/check-solid.svg",
fill=$color-checkmark) no-repeat center center;
}*Colorable means: the SVG can be recolored by CSS using the fill property,
if the SVG doesn't have any inline fill attributes (like fill="#000").
In that case you can't override it by CSS.
Note: you can use color codes or local SASS variables, but not CSS variables
in the fill properties. (the inline svg from CSS not supports CSS variables)
All JavaScript files should be written in ES6 syntax. All source JavaScript
files must go to src/js/ directory. Then we transform them with Babel.js into
ES5 form to the js/ directory. All JS files are categorized according to
SMACSS/ITCSS rules:
- base: for very generic functions
- tools: functions to solve a specific problem but not related a component/block
- objects: very generic, layout-related functions
- components: components related functions (the most will come here)
- theme: theming related functions
Because we have use Drupal libraries, we must create JS files for each library.
As mentioned above this Starterkit doesn't base on any base theme. All functions, templates are stand-alone: originally copied from core/contrib modules, from the core's Starterkit theme or from Olivero.
All templates should be organized in subdirectory according to core/contrib
modules. If you need to create a custom template, what you want to include
multiple places place them into the templates/_patterns/ directory.
Place your own components here: components/. By default there is the Icon
component which is used to display inline SVG icons in the Twig files,
generated from the /images/icons/ directory.
All custom/local hosted webfonts should go to the fonts/ directory.
By default as sample some Open Sans font files has been generated here.
All theme related images should be stored and organized in the images/
directory. Before place any image file here, please optimize that!
Icons should be stored in the images/icons/ directory in SVG format. They can
be used in the Icon component from here.
If you need to install any third party library please install that via composer and attach as a library.
If not setup in your project, you can follow this guide: How to manage front-end JavaScript libraries with composer in Drupal
For example, if you want to install Lity as
Search for in Asset Packagist repository. If you find that, you will see it's an npm or a bower package, then install them via Composer:
ddev composer require npm-asset/lityIt will install all assets into libraries/ directory, so we can add it
very easily into a library in the third party libraries section of the
brainsum_starterkit.libraries.yml file:
lity:
version: 2.4.1
remote: https://github.com/jsor/lity
license:
name: MIT
url: https://github.com/jsor/lity/blob/master/LICENSE
gpl-compatible: true
css:
theme:
/libraries/lity/dist/lity.min.css: { minified: true, preprocess: false }
js:
/libraries/lity/dist/lity.min.js: { minified: true, preprocess: false }We use JustValidate for client-side form
validation. It replaces native HTML5 browser validation with custom, themable
error messages. All validation strings are translatable via Drupal.t().
Install it via Composer (requires asset-packagist repository configured in your project):
ddev composer require npm-asset/just-validateThe theme provides a forms.validate Drupal library that auto-discovers fields
with HTML5 validation attributes (required, type="email", pattern, etc.)
and maps them to JustValidate rules. Attach it to any form where you want
client-side validation.
For full API documentation and custom rules, see the JustValidate docs.
We use Choices.js for enhanced select dropdowns with search and multi-select capabilities. It provides a modern, accessible alternative to native select elements.
Install it via Composer (requires asset-packagist repository configured in your project):
ddev composer require npm-asset/choices.jsThe theme provides a forms.choices Drupal library that automatically
initializes Choices.js on select elements with the multiple attribute or
custom data attributes. Attach it to any form where you want enhanced select
functionality.
For full API documentation and customization options, see the Choices.js docs.
We use only simple npm scripts to build css and js files. You can found all
scripts in package.json file. There are many but here is a recap which you
should use only:
start: compile and watching for all css and js files,build: compile all css and js files at once for production.
So for local developing just run in theme's root:
ddev yarn start...and before commit anything run:
ddev yarn buildFor even more convenience, you can use the following DDEV commands as well from anywhere in the project:
# It will install all required node packages and build the theme
ddev build# It will compile and watch for all css and js files and start browsersync
ddev devIf you want to use browsersync and not use the ddev dev command follow these steps:
- CD to the theme's root directory
- Run
ddev browsersyncto start the sync process - Open a new terminal tab
- Run
ddev yarn startto start watching for changes