Architecture
Extensions
Extensions are versioned packages that add features to Paradigm CMS without modifying core.
Directory layout
The runtime selects the configured version, or the latest semantic version available in the folder. Every extension follows this structure:
extensions/<extension_slug>/<version>/
├── extension-manifest.json
├── README.md
├── src/
│ ├── init.php
│ ├── config.php
│ ├── install.php
│ ├── config/
│ │ ├── objects/
│ │ │ └── <object_name>.json
│ │ └── widget.php
│ ├── API/
│ │ ├── config.php
│ │ ├── requests/
│ │ │ ├── <action>.php
│ │ │ └── <entity>/
│ │ │ ├── create.php
│ │ │ ├── update.php
│ │ │ ├── delete.php
│ │ │ ├── list.php
│ │ │ └── get.php
│ │ └── REST/
│ │ └── <resource>/
│ │ ├── get.php
│ │ ├── post.php
│ │ ├── put.php
│ │ └── delete.php
│ ├── blocks/
│ │ ├── admin/
│ │ │ ├── dashboard.php
│ │ │ └── <entity>/
│ │ │ ├── list.php
│ │ │ ├── create.php
│ │ │ └── edit.php
│ │ ├── public/
│ │ │ └── <block_name>.php
│ │ └── widget/
│ │ └── <block_name>.php
│ ├── classes/
│ ├── layouts/
│ │ └── admin/
│ │ └── index.php
│ ├── assets/
│ │ ├── js/
│ │ ├── css/
│ │ └── images/
│ ├── widget/
│ │ └── views/
│ └── lib/
Extension manifest
Each extension root contains an extension-manifest.json with metadata:
{
"slug": "extension_name",
"version": "1.0.0",
"repository": "https://github.com/org/repo"
}
init.php — hook config class
The init.php file defines a config class that hooks into the CMS lifecycle.
This is the only place a PHP class is allowed in extension code (aside from classes/).
<?php
class extension_slug_config {
function end_of_head() {
$html = '';
echo $html;
}
function admin_end_of_head() {
$html = '';
echo $html;
}
}
?>
API/config.php — action mapping
Maps human-readable action names to handler file names:
<?php
$API_CONFIG = array(
'{entity}' => array(
'actions' => array(
'create' => 'create_{entity}',
'list' => 'list_{entities}',
'update' => 'update_{entity}',
'delete' => 'delete_{entity}'
)
)
);
?>
install.php — schema initialization
Optional file that runs during extension activation to seed baseline data:
<?php
if (!defined('ROOT_DIR')) { header("HTTP/1.1 403 Not Found"); exit(); }
$existingPage = PAPI_get_object('core:page', array(
array(array('slug', '=', '{page_slug}'))
), 'internal');
if ($existingPage === false) :
PAPI_create_object('core:page', array(
'label' => '{Page Label}',
'slug' => '{page_slug}',
'status' => 'active'
), 'internal');
endif;
Schema setup
The core schema updater reads JSON object definitions from src/config/objects/ and builds
database tables and meta tables. Schema files use singular names (article.json) and
the infoKeys/metaKeys format. See Database schema for the full format.
Enabling extensions
Extensions must be enabled in siteConfig.php under the extensions key.
The schema updater refuses to run if the extension is not enabled.
Activation workflow
Extensions can provide an activate request. The core installer triggers
extension:activate for required extensions during initial setup. Core activation
demonstrates the pattern by updating schema and creating baseline pages.
AI-first extension checklist
- Provide a clear
README.mdat the extension root describing APIs and blocks. - Keep request names short and consistent for predictable
extension:requestlookups. - Document block slugs alongside file paths so AI can navigate quickly.
- Version extensions semantically to support deterministic upgrades.