Divi 5 Tutorial Simple Quick Module
A single WordPress plugin that registers multiple custom Divi 5 modules. Modules are built using the Divi 5 Module API and share one compiled JS bundle.
by Elegant Themes · github.com/notsotraditional/divi-5-modules-plugin
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/notsotraditional/divi-5-modules-plugin/archive/refs/heads/main.zipReadme
Divi 5 Custom Modules Plugin
A single WordPress plugin that registers multiple custom Divi 5 modules. Modules are built using the Divi 5 Module API and share one compiled JS bundle.
AI Agent Context
This section is written for AI coding assistants (Claude, Copilot, etc.). Read this before making any changes to the plugin.
Plugin folder name
Action required: The plugin folder is currently named
divi-extensionwhich is a generic placeholder. Rename it to something that reflects the project or the part of the site these modules serve — for examplesite-divi-modulesorsite-blog-modules. Update the constants ind5-tutorial-simple-quick-module.php(D5_TUTORIAL_SIMPLE_QUICK_MODULE_PATH,D5_TUTORIAL_SIMPLE_QUICK_MODULE_URL) to match if you rename the main PHP file too.
What this project is
A WordPress plugin that registers custom modules for the Divi 5 visual builder. It is not a Divi 4 plugin — do not use ET_Builder_Module PHP classes or Divi 4 shortcode patterns. Everything here uses the Divi 5 Module API.
How the plugin is wired together
- One plugin entry point —
d5-tutorial-simple-quick-module.php. It enqueues one JS bundle andrequire_onces one PHP file per module. - One JS bundle —
visual-builder/build/d5-tutorial-simple-quick-module.js, compiled fromvisual-builder/src/index.jsxwhich imports each module's ownindex.jsx. - One PHP class per module — lives in
server/, implementsDependencyInterface, registers the module oninitand wires up render/style callbacks. - One
module.jsonper module — the single source of truth for attributes, selectors, and which Design tab panels appear. Both PHP and JS import this file.
Established conventions — follow these exactly
groupLabelis required on any decoration group that appears on more than one element. Without it, Divi renders duplicate tabs with the same default name (e.g. two "Body Text" panels). Always name it after the element:"Title Spacing","Content Text","Food Options Spacing".layoutbelongs only on themoduleattribute — never on child elements liketitle,content, or custom text elements. Adding it to sub-elements creates redundant Layout tabs in the Design tab.defaultsets the baked-in attribute value — use this for spacing or other decoration values that should pre-populate. It is separate fromplaceholderContent(which is only the initial content when a module is first inserted).- Always rebuild after editing
module.jsonor any.jsxfile — runnpm run buildfrom thevisual-builder/directory. Changes to PHP files take effect immediately without a build. - Namespaces must be unique per module — PHP server files use namespaces like
D5Tut\SimpleQuickModule2. Never reuse the same namespace across files.
Adding a new module — checklist
- Create
visual-builder/src/your-module/module.jsonandindex.jsx - Import it in
visual-builder/src/index.jsx - Create
server/YourModule.php— update$module_json_folder_pathto match the new folder - Add
require_oncefor the new PHP file ind5-tutorial-simple-quick-module.php - Run
npm run build
Known gotchas
- If a decoration group appears empty in the Design tab (header visible but no fields), it usually means all fields in that group have
render: false. Divi renders the group shell regardless — remove the group fromsettings.decorationentirely if you don't want it visible. - The
module.jsonis read by both PHP (ModuleRegistration::register_module) and JS (registerModule). The PHP class points to the folder containingmodule.json, not the file itself. - There is no git workflow yet — deployment is manual FTP upload of the full plugin folder.
Structure
divi-extension/
├── d5-tutorial-simple-quick-module.php # Plugin entry point — registers assets, requires server files
├── server/
│ ├── index.php # Module 1 — PHP render + style callbacks
│ └── SimpleQuickModule2.php # Module 2 — PHP render + style callbacks
└── visual-builder/
├── package.json
├── webpack.config.js
└── src/
├── index.jsx # Root entry — imports all modules
├── simple-quick-module/
│ ├── module.json # Module metadata & attribute definitions
│ └── index.jsx # Visual Builder renderer + registerModule call
└── simple-quick-module-2/
├── module.json
└── index.jsx
Adding a New Module
1. Create the Visual Builder files
Add a new folder under visual-builder/src/your-module-name/ with:
module.json— defines the module name, attributes, and which design settings appear in the builder.index.jsx— registers the module withregisterModuleand defines the React renderer.
2. Register it in the root entry file
Add an import to visual-builder/src/index.jsx:
import "./your-module-name/index.jsx";
3. Create the PHP server file
Add server/YourModule.php implementing DependencyInterface. Point $module_json_folder_path at your module's folder:
$module_json_folder_path = dirname( __DIR__, 1 ) . '/visual-builder/src/your-module-name';
4. Require it from the plugin entry point
In d5-tutorial-simple-quick-module.php:
require_once D5_TUTORIAL_SIMPLE_QUICK_MODULE_PATH . 'server/YourModule.php';
5. Build
cd visual-builder
npm run build
Development Commands
| Command | Description |
|---|---|
npm run build |
Production build (minified) |
npm start |
Watch mode for development |
Run both from the visual-builder/ directory.
module.json Reference
Key fields for each attribute:
| Field | Purpose |
|---|---|
selector |
CSS selector for this element — use {{selector}} for the module wrapper |
tagName |
HTML tag rendered for the element |
inlineEditor |
"plainText" or "richText" — enables inline editing in the builder |
default |
Default attribute values applied on every instance |
placeholderContent |
Initial content inserted when the module is first added to a layout |
settings.decoration |
Which design control groups appear in the Design tab |
Decoration groups
Declare only the groups you need. Each key maps to a panel in the Design tab:
"decoration": {
"layout": {},
"background": {},
"spacing": {},
"border": {},
"boxShadow": {},
"sizing": {},
"font": {},
"bodyFont": {},
"filters": {},
"transform": {},
"animation": {},
"transition": {},
"position": {},
"zIndex": {},
"scroll": {},
"sticky": {},
"overflow": {},
"disabledOn": {}
}
Customising a decoration group
Use component.props to rename the group label or hide individual fields:
"bodyFont": {
"component": {
"props": {
"groupLabel": "Content Text",
"fields": {
"headingLevel": { "render": false }
}
}
}
}
Tips — Naming Groups and Fields
Always set a groupLabel on shared decoration types
When multiple elements declare the same decoration type (e.g. bodyFont, spacing), Divi renders a panel for each one using the same default label. This results in duplicate tabs like two "Body Text" or two "Spacing" groups in the Design tab.
Fix this by adding a groupLabel to every element that shares a decoration type:
"bodyFont": {
"component": {
"props": {
"groupLabel": "Content Text"
}
}
}
"bodyFont": {
"component": {
"props": {
"groupLabel": "Food Options Text"
}
}
}
Apply the same pattern to spacing, font, border, or any other group that appears on more than one element.
Only declare layout on the module element
The layout decoration group controls display, alignment, and overflow at the module level. Declaring it on sub-elements (title, content, etc.) adds a redundant Layout tab for each one. Keep layout only under the top-level module attribute:
"module": {
"settings": {
"decoration": {
"layout": {}
}
}
}
Remove it from any child elements.
Use descriptive labels that match the element
Name each group after the element it controls so editors can identify them at a glance:
| Element | groupLabel examples |
|---|---|
| Title | "Title Font", "Title Spacing" |
| Content | "Content Text", "Content Spacing" |
| Food Options | "Food Options Text", "Food Options Spacing" |
Deployment
There is currently no formal git workflow in place. To deploy changes to the live server:
- Run
npm run buildlocally to produce an updatedvisual-builder/build/d5-tutorial-simple-quick-module.js - FTP into the server
- Replace the entire plugin folder (
wp-content/plugins/divi-extension/) with the updated local version - Verify the modules still appear correctly in the Divi visual builder
Once a git workflow is established this section should be updated to reflect that process.