Documentation
Creating Modules
Technical guidance for adding first-party DesertCMS modules with settings, public routes, capability mapping, plan gates, renderer output, and tests.
CREATING_MODULES.mdDesertCMS modules are first-party feature surfaces, not external plugins. A module usually has a settings flag, optional public output, admin UI, capability policy, renderer behavior, and tests.
Module Definition
Add the module to lib/DesertCMS/Modules.pm.
A definition should include:
{
key => 'example',
label => 'Example',
description => 'Adds the public /example/ page and example settings.',
public_path => '/example/',
settings_path => '/admin/settings/modules/example',
setting_key => 'module_example_enabled',
default_plan_enabled => 0,
}
If the module is master-managed on contributor sites, add:
managed_by_master_contributor => 1
Settings
Add a default setting in DesertCMS::Config:
module_example_enabled => 0,
If the setting must persist through the admin settings UI, wire it through the relevant DesertCMS::Settings save path and admin form.
Plan Gates
Contributor plans use the module feature map.
The module catalog computes:
availableenabledconfigured_enabledlocked_by_planrequires_upgrademanaged_by_master
Do not hide a master-managed contributor feature only by removing a link. The module state should explain whether the feature is plan-locked or platform-managed.
Capability Policy
Map admin routes in DesertCMS::CapabilityPolicy.
Use read/write capability pairs when possible:
return _read_or_write($method, 'view_features', 'enable_allowed_modules') if _matches(
$path,
qr{\A/admin/settings/modules/example(?:/|\z)}
);
If the module has public admin content editing, use view_content and edit_content. If it changes design, use view_design and customize_theme. If it is an operator task, use an operations or provider capability.
Contributor mode should block master-managed routes in _contributor_master_managed_route.
Admin UI
Use the existing admin shell and product split:
- Master-only modules can appear under MasterCMS settings or operations.
- Contributor-available modules should appear in Features.
- Contributor content tools should use site-builder language.
- Platform-managed options should say they are managed by the platform.
- Plan-locked options should point to Billing or upgrade.
Avoid operator terms on contributor pages.
Public Rendering
If the module writes a public page, add renderer behavior in DesertCMS::Renderer.
The normal pattern is:
- Check whether the module is enabled.
- Skip generated output if published content claims the same URL.
- Render through the shared public module shell.
- Write into
public_root. - Remove generated artifacts when disabled.
Generated pages should use the same theme and layout as other public content.
Routes
Public module routes may need httpd forwarding if they are dynamic CGI routes, such as forms or shop checkout.
Static generated module pages do not need CGI forwarding once written to the public root.
Schema
If the module needs database tables, add them to sql/schema.sql and migration code through the existing migration flow.
Keep tenant ownership explicit for contributor-facing data. Bind destructive operations to the exact owner or site record.
Media
If the module uses media:
- Use
DesertCMS::Media. - Do not expose private source paths.
- Use public image derivatives for images.
- Use Resource Downloads for public non-image files.
- Respect media capabilities and plan limits.
Tests
Add or update tests for:
- Module definition.
- Settings default.
- Enabled and disabled public output.
- Plan-gated feature state.
- Contributor mode route policy.
- Renderer cleanup when disabled.
- Admin terminology when contributor-accessible.
- Public route behavior.
For module-gated editor controls, preserve stored values when a feature is disabled. Do not clear fields just because the UI panel is hidden.