Modularity Custom Modules
A simple WordPress plugin for adding custom Modularity modules to the Municipio theme.
by Linu George · github.com/georgelinu/modularity-custom-modules · website
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/georgelinu/modularity-custom-modules/archive/refs/heads/main.zipA simple WordPress plugin for adding custom Modularity modules to the Municipio theme.
Description
To create custom modularity-modules for Municipio. This plugin is a template to create custom modules. The modules are auto-discovered by placing them in the /modules/ folder, and the ACF fields are auto-discovered by placing them in the /acf-fields/php/ and /acf-fields/json/ folder. The blade views are auto-discovered by placing them in the /modules/ModuleName/views/ folder.
Requirements
- WordPress 6.0+
- Municipio 5.0+
- Modularity plugin (bundled in Municipio, or install standalone)
- Advanced Custom Fields PRO
Note: This plugin will not work without all of the above active. It silently does nothing if Modularity or ACF PRO is missing.
Installation
- Download or clone this plugin into your WordPress plugins directory:
wp-content/plugins/ - Log in to WordPress admin and go to Plugins → Installed Plugins.
- Activate Modularity Custom Modules.
- Enable the required modules in "Modularity Options".
- Go to any page that uses Modularity and click Add Module — you should now see the custom Blocks listed as an available module.
File Structure for the plugin
modularity-custom-modules/
│
├── modularity-custom-modules.php ← Plugin root file.
│
├── assets/
│ ├── css/
│ │ ├── style.css ← Shared styles applied to every module.
│ │ └── HeadingModule.css ← Module-specific styles (one file per module).
│ └── js/
│ ├── main.js ← Shared JS loaded on every page.
│ └── HeadingModule.js ← Module-specific JS (one file per module).
│
├── acf-fields/
│ ├── json/
│ │ └── HeadingModule.json ← One file per module (filename must match the module name).
│ └── php/
│ └── HeadingModule.php ← One file per module (filename must match the module name).
│
└── modules/
└── HeadingModule/ ← One folder per module.
├── HeadingModule.php ← Module class:
│ - Defines slug, name, and description.
│ - Enqueues module assets.
│ - Passes data to the view.
└── views/
└── heading-module.blade.php ← Blade template for rendering.
How to Add a New Module
Follow these steps every time you want a new module:
- Create a folder: modules/YourModule/
- Add class file: modules/YourModule/YourModule.php
- Add blade view: modules/YourModule/views/your-module.blade.php
- Add ACF PHP: acf-fields/php/YourModule.php (export from WP Admin)
- Add ACF JSON: acf-fields/json/YourModule.json (export from WP Admin)
Step 1 — Create the folder and files
modules/
└── MyModule/
├── MyModule.php
└── views/
└── my-module.blade.php
Step 2 — Create the module class
Copy modules/HeadingModule/HeadingModule.php into your new folder and rename the class. Then update:
What to change
- Namespace (
ModularityCustomModules\Modules\MyModule) - Class name (
MyModule) - Slug (
$slug: A unique slug, e.g.mcm-my-module) - Name (
$this->nameSingular/$this->namePlural: Human-readable names, e.g.My Module/My Modules) - Description (
$this->description) - Template return value (
template():'my-module.blade.php')
Step 3 — Create the view
Copy modules/HeadingModule/views/heading-module.blade.php into modules/MyModule/views/my-module.blade.php and update the HTML/variables to match your module.
Step 4 — Register ACF fields (PHP) for a module
- Create the field group using ACF.
- Export the field group to PHP (using ACF's export tool).
- Place the exported PHP file in acf-fields/php/YourModule.php
Note: The filename must match the module-name.
Step 4 — Register ACF fields (JSON) for a module
- Create the field group in WP Admin using ACF.
- Export the field group to JSON (using ACF's export tool).
- Place the exported JSON file in acf-fields/json/YourModule.json
Note: The filename must match the module-name.
That's it — Modularity will automatically detect the new module.
ACF Fields Reference
Fields are defined in the registerAcfFields() method of each module class.
Note: Full ACF field type reference: Advanced Custom Fields
Reading field values in data()
See the below examples on how to get values from ACF.
// 1. Simple field value.
$data['my_field'] = get_field('mcm_my_module_my_field', $post->ID) ?: '';
// 2. Image field value (returns an array).
$image = get_field('mcm_my_module_image', $post->ID);
$data['image_url'] = $image['url'] ?? '';
$data['image_alt'] = $image['alt'] ?? '';
// 3. Repeater field value(returns an array of rows).
$data['items'] = get_field('mcm_my_module_items', $post->ID) ?: [];
Outputting values in the Blade view
See the below examples on how to render the UI.
{{-- Plain text (HTML escaped — safe) --}}
{{ $my_field }}
{{-- HTML content from WYSIWYG (not escaped — trusted admin content) --}}
{!! $content !!}
{{-- Conditional output --}}
@if (!empty($title))
<h2>{{ $title }}</h2>
@endif
{{-- Looping a repeater --}}
@foreach ($items as $item)
<p>{{ $item['label'] }}</p>
@endforeach
CSS & JS
- Shared styles (applied to every module):
assets/css/style.css - Module-specific styles:
assets/css/MyModule.css(enqueued in the module'sstyle()method) - Shared JS (loaded on every page):
assets/js/main.js - Module-specific JS:
assets/js/MyModule.js(enqueued in the module'sscript()method)
Module Icon Names
Icons come from the Google Material Icons set used by Municipio. Browse all available icons at: Google Icons
Use the icon's name in snake_case as the $moduleIcon value in your module class. Examples: text_fields, image, info, contact_page, list, article.
Naming Conventions Used
To avoid conflicts with other plugins, this plugin uses the mcm_ prefix consistently:
Examples
PHP namespace: ModularityCustomModules\Modules\ModuleName
Post type: mod-{module-name}, mod-text-block
ACF group key: group_mcm_{module_name}, group_mcm_text_block
ACF field key: field_mcm_{module}_{field}, field_mcm_text_block_title
ACF field name: mcm_{module}_{field}, mcm_text_block_title
CSS class on wrapper: modularity-{module-name}, modularity-text-block
Troubleshooting
If Module doesn't appear in the Modularity module
- Make sure all the connected plugins are active.
- Check that your module class file has no PHP syntax errors.
ACF fields don't appear on the module edit screen
- Make sure ACF PRO is active.
- Check the
locationrule in your ACF PHP file — thevaluemust exactly match your module's$slugprefixed withmod-(e.g.mod-mcm-heading).
The view isn't rendering/blank output
- Confirm the path returned by
template()matches the actual file path relative to the plugin root. - Check for PHP/Blade syntax errors in the view file.
For enquiry about the plugin, please contact at Linu George
Changelog
1.0.0
- Initial release with auto-discovery for modules, ACF fields, and Blade views.
License
MIT — free to use, modify, and share.