WP Manifestindependent plugin directory
manifest / builders / divi-5-modules-plugin

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

0stars
0forks

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.zip

Readme

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-extension which is a generic placeholder. Rename it to something that reflects the project or the part of the site these modules serve — for example site-divi-modules or site-blog-modules. Update the constants in d5-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 pointd5-tutorial-simple-quick-module.php. It enqueues one JS bundle and require_onces one PHP file per module.
  • One JS bundlevisual-builder/build/d5-tutorial-simple-quick-module.js, compiled from visual-builder/src/index.jsx which imports each module's own index.jsx.
  • One PHP class per module — lives in server/, implements DependencyInterface, registers the module on init and wires up render/style callbacks.
  • One module.json per 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

  • groupLabel is 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".
  • layout belongs only on the module attribute — never on child elements like title, content, or custom text elements. Adding it to sub-elements creates redundant Layout tabs in the Design tab.
  • default sets the baked-in attribute value — use this for spacing or other decoration values that should pre-populate. It is separate from placeholderContent (which is only the initial content when a module is first inserted).
  • Always rebuild after editing module.json or any .jsx file — run npm run build from the visual-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

  1. Create visual-builder/src/your-module/module.json and index.jsx
  2. Import it in visual-builder/src/index.jsx
  3. Create server/YourModule.php — update $module_json_folder_path to match the new folder
  4. Add require_once for the new PHP file in d5-tutorial-simple-quick-module.php
  5. 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 from settings.decoration entirely if you don't want it visible.
  • The module.json is read by both PHP (ModuleRegistration::register_module) and JS (registerModule). The PHP class points to the folder containing module.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 with registerModule and 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:

  1. Run npm run build locally to produce an updated visual-builder/build/d5-tutorial-simple-quick-module.js
  2. FTP into the server
  3. Replace the entire plugin folder (wp-content/plugins/divi-extension/) with the updated local version
  4. 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.


Helpful Documentation

Read the full README on GitHub →