Extensions Overview Since 3.3.0
The Total CMS extension system lets you add custom functionality without modifying core files. Extensions can add Twig functions and filters, CLI commands, admin pages, REST API endpoints, custom field types, event listeners, dashboard widgets, and schemas.
How Extensions Work
Section titled “How Extensions Work”Extensions follow a two-phase lifecycle:
- Register — declare what your extension provides (Twig functions, CLI commands, etc.)
- Boot — wire into the running application (subscribe to events, resolve services)
Every extension implements the ExtensionInterface and interacts with Total CMS through an ExtensionContext object that provides a stable, versioned API.
Directory Structure
Section titled “Directory Structure”Extensions live in tcms-data/extensions/{vendor}/{extension-name}/:
tcms-data/extensions/ acme/ seo-pro/ extension.json # Manifest Extension.php # Entry point (implements ExtensionInterface) src/ # Additional PHP classes schemas/ # Read-only schemas (Pro+ only) templates/ # Twig templates assets/ # CSS, JS, imagesQuick Example
Section titled “Quick Example”A minimal extension that adds a Twig function:
extension.json:
{ "id": "acme/hello", "name": "Hello Extension", "version": "1.0.0", "permissions": ["twig:functions"], "entrypoint": "Extension.php", "license": "MIT"}Extension.php:
<?php
namespace Acme\Hello;
use TotalCMS\Domain\Extension\ExtensionContext;use TotalCMS\Domain\Extension\ExtensionInterface;use Twig\TwigFunction;
class Extension implements ExtensionInterface{ public function register(ExtensionContext $context): void { $context->addTwigFunction( new TwigFunction('hello', fn (string $name): string => "Hello, {$name}!") ); }
public function boot(ExtensionContext $context): void { // Nothing to do on boot for this simple extension }}Use it in a template:
{{ hello('World') }}{# Output: Hello, World! #}Edition Requirements
Section titled “Edition Requirements”Extensions can declare a minimum edition in their manifest:
{ "min_edition": "pro"}Valid values: lite (default), standard, pro. Extensions that require a higher edition than the site’s license are not loaded.
Extension-provided schemas always require Pro or higher, regardless of the min_edition setting.
Fault Isolation
Section titled “Fault Isolation”A broken extension cannot crash Total CMS. If an extension throws an exception during register() or boot():
- The exception is caught and logged to
logs/extensions.log - The error is recorded in the extension’s state (visible in the admin UI)
- Other extensions continue loading normally
- The site operates without the broken extension
Managing Extensions
Section titled “Managing Extensions”Admin UI: Navigate to Settings > Extensions to see all installed extensions, enable/disable them, and view errors.
CLI:
tcms extension:list # List all extensionstcms extension:enable vendor/name # Enable an extensiontcms extension:disable vendor/name # Disable an extensiontcms extension:remove vendor/name # Remove extension filesStarter Template
Section titled “Starter Template”Clone the extension-starter repo to get a working extension with examples of every extension point:
cd tcms-data/extensions/mkdir your-vendor && cd your-vendorgit clone https://github.com/totalcms/extension-starter.git your-extensioncd your-extension && composer installtcms extension:enable your-vendor/your-extensionNext Steps
Section titled “Next Steps”- Manifest Reference — all manifest fields explained
- Extension Points — what extensions can do
- Events — subscribing to content events
- Schemas — providing schemas from extensions