Mai Engine WP Registry grade D+. High-severity findings · 2 findingsWP RegistryHigh-severity findings · 2 findingsOpen the reportD+
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/maithemewp/mai-engine/archive/refs/heads/develop.zipThe required plugin to power Mai themes.
Development
Mai Engine makes use of two package managers, NPM for JavaScript and Composer for PHP packages.
Handy CLI commands
Important: Remember to specify the --url parameter if on multisite. E.g --url=demo.bizbudding.com/success-business.
wp mai generate- Generates starter content for a site (Home page etc).wp option delete 'mai-engine'- Deletes all setting options.
Setup the development environment
-
Clone this repository into your WordPress site's
pluginsdirectory.git clone https://github.com/maithemewp/mai-engine.git -
Change directories into the plugin folder from the command line:
cd mai-engine -
Install Composer and any PHP dependencies with the following command:
composer installPlease note that this step requires that you have Composer installed globally on your machine. We recommend using Homebrew to install Composer:
brew install composerexport PATH="$HOME/.composer/vendor/bin:$PATH" -
Install Node packages:
npm installPlease note that this step requires that you have Node installed globally on your machine. We recommend using Homebrew to install Node:
brew install node
Composer scripts
Mai Engine uses PHP Code Sniffer for linting and fixing coding standards. To lint all PHP files against WordPress coding standards run the following command:
composer phpcs
To have PHP Code Sniffer attempt to automatically fix any warnings run the following:
composer phpcbf
Testing
Two suites. The unit suite runs with no WordPress and no database, using brain/monkey to
mock WordPress functions. The integration suite boots real WordPress via wp-phpunit and
needs MySQL.
Test dependencies live in their own Composer project at tests/composer.json and install to
tests/vendor/. That is deliberate: the plugin deploys as a raw git tree with no build step,
so the committed vendor/ autoloader must never contain dev entries. Keeping the test
dependencies out of the root project means running the suites cannot regenerate it.
Setup
composer test-setup # installs tests/vendor, one time
mysql -u root -e "CREATE DATABASE mai_engine_tests" # integration suite only, one time
npm install and composer install do not install the test dependencies. If
composer test-unit reports tests/vendor/bin/phpunit: No such file or directory, run
composer test-setup.
Running
composer test-unit # no WordPress, no database, sub-second
composer test-integration # boots WordPress, needs MySQL
composer test # both
Database connection is read from WP_TESTS_DB_NAME, WP_TESTS_DB_USER, WP_TESTS_DB_PASS
and WP_TESTS_DB_HOST, defaulting to mai_engine_tests / root / empty / 127.0.0.1.
Warning: the WordPress test bootstrap drops the WordPress core tables carrying the
configured $table_prefix in the configured database, on every run. It does not drop every
table, but pointing it at a real site's database with a matching prefix will destroy that
site's content. Keep the dedicated database name.
Notes
wp-phpunit/wp-phpunitandroots/wordpress-no-contentintests/composer.jsonare meant to track together. Bump both, and only viacomposer update -d tests.- The integration suite boots WordPress but does not activate the plugin, because
lib/init.phpexpects Genesis as the parent theme. Tests load the specificlib/files they exercise viatests/phpunit/integration/plugin-loader.php. - Integration tests extend
MaiIntegrationTestCase, notWP_UnitTestCasedirectly. The base class works aroundWP_UnitTestCasecalling PHPUnit 9 APIs that PHPUnit 10 removed. - Encoding fixture goldens are generated, not hand-written. Regenerate with
php tests/phpunit/unit/fixtures/generate.phpand review every changed golden by hand.
NPM scripts
Mai Engine utilizes Gulp and Sass to automate tedious tasks, such as automatically generating the many stylesheets required by the child themes.
First you will need to install NPM on your machine:
brew install npm
It is also recommended to install NVM (Node Version Manager) to allow easy switching of Node versions:
brew install nvm
Next, install the Gulp CLI globally on your machine. To install Gulp CLI run the following command from the terminal:
sudo npm install gulp-cli -g
Now that all of the global packages are installed, navigate to the root directory of this plugin, e.g:
cd Sites/my-project/wp-content/plugins/mai-engine
From there, make sure that Node is running the correct version (11.15.0). To do this, you will first need to run some commands to configure nvm correctly. A simple composer script is provided:
composer setup-nvm
Build & Release Scripts
| Command | Description |
|---|---|
npm start |
Build all assets and watch for changes |
npm run release |
Full production build: validate composer, build assets, strip dev deps |
npm run beta |
Build assets, commit, push develop, merge/push beta, restore dev deps |
npm run dev |
Restore dev dependencies after a release build |
Beta release workflow:
- Bump the version in
mai-engine.php(e.g.2.39.0-beta.1) - Update
CHANGES.mdwith changelog entries - Run
npm run beta
Production release workflow:
- Set the final version in
mai-engine.php(e.g.2.39.0) - Update
CHANGES.md - Run
npm run release - Commit and push manually
Gulp
Once the Gulp CLI and Node packages have been installed, you are ready to begin using the following Gulp tasks to automate development:
Default
Running the default gulp task will kick of development and Gulp will watch files for changes. When a change to a file is detected Gulp will run the build tasks and recompile assets.
gulp
CSS
gulp build:css
JS
gulp build:js
To create a new engine theme
gulp create --name=themename --composer
Using the CSS system
Goals of the CSS system: Keep it DRY. Prioritize performance.
Please note: files in the assets/css/ directory should never be edited directly as any changes will be overridden when running the gulp build task. All changes should be made to the SCSS files in the assets/scss/ directory and then compiled using the gulp build:css command.
Organization
This project follows the ITCSS principal to organize the CSS files in such a way that they can better deal with CSS specificity. One of the key principles of ITCSS is that it separates your CSS codebase to several sections (called layers), which take the form of the inverted triangle. The structure is also based on the Sass Guidelines. More information about ITCSS can be found here.
- Abstracts – used with preprocessors and contain font, colors definitions, globally used mixins and functions. It’s important not to output any CSS in this layer.
- Base – reset and/or normalize styles, box-sizing definition, styling for bare HTML elements (like H1, A, etc.). These come with default styling from the browser so we can redefine them here. This is the first layer which generates actual CSS.
- Layout – the layout/ folder contains everything that takes part in laying out the site or application. These elements are usually only in one place and contain multiple components.
- Components – specific UI components. This is where the majority of our work takes place and our UI components are often composed of Objects and Components
- Utilities – utilities and helper classes with ability to override anything which goes before in the triangle, eg. hide helper class
- Plugins - styling for third party plugins. Not imported in the main stylesheet.
- Themes - theme specific styling. Should only contain custom property overrides if possible. Should be thought of as a config file.
Color variables
Mai Engine uses both element-color and color-element naming convention for color variables, here's an explanation on how to use them:
var(--color-element)
These custom properties are the ones automatically generated by the theme config and Customizer settings. They should be thought of as the "color palette" and never be changed directly via CSS.
In the theme or engine CSS we use them in places like this:
/* Correct way to set a dark background for the site footer */
.site-footer {
background-color: var(--color-heading);
}
We would never want to change the values like this, as it could affect the parent element if it is using a .has-heading- utility class:
/* Wrong way to make all headings in the site footer white */
.site-footer {
--color-heading: var(--color-white);
}
var(--element-color)
These are the element custom properties that can be changed depending on their context, for example we can do this:
/* Right way to make all headings in the site footer white */
.site-footer {
--heading-color: var(--color-white);
}
But we shouldn't use them like this, because the custom property may not be set:
/* Wrong way to set a dark background for the site footer */
.site-footer {
background-color: var(--heading-color);
}
To summarise, we have the "color palette", which are globals and should never be changed in the CSS. They can only be changed from the theme config or the Customizer settings. Then we also have the "element properties" which should be used to change an elements styles depending on the context.
Kirki custom fixes/overrides
Kirki is vendored by hand and carries local patches. See patches/README.md for the authoritative list, with real diffs, the reasoning behind each one, and the paths they move to in Kirki 5.2.x.
Summary as of 2026-08-26:
kirki-packages/data-option/src/Option.phpreturns a field's declared$defaultrather than an empty string when a nested option key is missing.kirki-packages/module-webfonts/src/Webfonts/Downloader.phpcarries one commented out line recording the old Safari user-agent. It is inert and safe to drop.
Two entries previously listed here were wrong and have been removed. The Firefox user-agent was never our change, upstream shipped it in 5.1.0 (commit 6908691b) 49 minutes before the commit we vendored. And the md5( $url ) filename change was removed on 2026-08-26 because it stripped the .woff2 extension, so servers could not match font MIME or cache rules and every repeat visitor re-downloaded the fonts. patches/README.md records that with the measurements.
Releases
Newest 25 of 60 recorded releases.
These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.