How to Create Modules

What is a Zero CMS Module?

A Module in Zero CMS is a self-contained, isolated, and decoupled package containing related Models, Controllers, and Views. Modules reside under src/Modules/[ModuleName]/. Toggling a module off at the site level automatically blocks its routes, widgets, and console submenus globally!

Module Directory Structure

Establish your module's folder tree conforming with the following strict naming conventions:

src/Modules/Shop/
├── Controllers/
│   ├── CatalogController.php
│   └── CartController.php
├── Models/
│   ├── Product.php
│   └── Order.php
└── Views/
    └── dashboard-widget.php

Enforcing Route-Level Module Toggles

To enforce module toggles globally, register your routes inside src/Middleware/Router.php and intercept requests based on active tenant permissions:

// Inside src/Middleware/Router.php

if ($moduleName !== null) {
    $site = \Zero\Core\App::getCurrentSite();
    if ($site && !$site->isModuleEnabled($moduleName)) {
        continue; // Bypasses routing dynamically! (Renders 404)
    }
}

Decoupled Dashboard Widgets

Modules can register visual workspace cards by defining Views/dashboard-widget.php. It is dynamically loaded if the module is enabled, and integrates with the layout preferences:

<!-- Inside src/Modules/Shop/Views/dashboard-widget.php -->
<?php if (in_array('recent_orders', $enabledWidgets ?? [])): ?>
  <div class="dashboard-card">
      <h3>Recent Shop Orders</h3>
      <!-- Query and loop orders... -->
  </div>
<?php endif; ?>

Step-by-Step: Initializing and Activating your Module

To instantiate and fully activate your custom module, perform the following 3 steps:

  1. Write Module Logic: Create your Controller (e.g. src/Modules/Shop/Controllers/CatalogController.php) extending Zero\Interfaces\Controller.
  2. Register Routes in index.php: Use the Router::register() helper to map a regular expression path to your namespaced module controller:
    \Zero\Middleware\Router::register(
        '#^/shop/catalog$#',
        \Zero\Modules\Shop\Controllers\CatalogController::class
    );
  3. Turn the Module ON: Open your site's seeder JSON (or run a DB query) and insert the module's key (e.g. "shop") into the enabled_modules JSON column of the sites database table:
    "enabled_modules": ["shop"]