Registering an Extbase backend module 

Backend modules are registered via Configuration/Backend/Modules.php. This is the standard TYPO3 backend module registration mechanism which is not Extbase-specific. Extbase adds two extra keys to the configuration (extensionName and controllerActions) that tell TYPO3 to bootstrap Extbase and route requests to an ActionController .

Registering the module 

Create or extend Configuration/Backend/Modules.php in your extension. Return an array where each key is a unique module identifier and the values are the module configuration:

EXT:my_extension/Configuration/Backend/Modules.php
use MyVendor\MyExtension\Controller\ConferenceController;

return [
    'my_extension_conferences' => [
        'parent' => 'web',
        'position' => ['after' => '*'],
        'access' => 'user',
        'path' => '/module/web/my-extension-conferences',
        'iconIdentifier' => 'my-extension-conference-module',
        'labels' => 'my_extension.modules.conferences',
        'extensionName' => 'MyExtension',
        'controllerActions' => [
            ConferenceController::class => [
                'index', 'show', 'new', 'create', 'edit', 'update', 'delete',
            ],
        ],
    ],
];
Copied!

The Extbase-specific keys are:

extensionName
The extension name in UpperCamelCase, for example, if the extension key is my_extension the extension name will be MyExtension.
controllerActions
An array mapping controller class names to a list of allowed action names. The first entry and its first action are the default. Actions can be set as an array (as shown above) or as a comma-separated string.

These two keys instruct TYPO3 to bootstrap Extbase for this module. Do not use them for modules whose controllers do not extend ActionController . Use the standard routes key instead.

The remaining keys — parent, position, access, path, iconIdentifier, labels — are standard backend module configuration and apply to all modules regardless of whether they use Extbase or not. See Backend modules API for the full reference.

Access control 

The access key limits who can access the module:

  • 'user' — available to backend users who have been granted access in their user or group settings.
  • 'admin' — available to administrators only.
  • 'systemMaintainer' — available to system maintainers only.

User-level access ('user') requires permission to be explicitly granted in Backend Users > Edit > Modules. Admin-only modules skip this check.

Module labels 

The labels key accepts either a translation label reference or a translation domain string. Using the domain syntax introduced in TYPO3 v14:

'labels' => 'my_extension.modules.conferences',
Copied!

This resolves to EXT:my_extension/Resources/Private/Language/Modules/conferences.xlf. The middle segment (modules) becomes a subdirectory under Resources/Private/Language/; the last segment (conferences) becomes the filename. The file should define the key title and optionally description and shortDescription.

The legacy LLL:EXT: syntax is equally valid and remains fully supported.

Rendering in the module controller 

Extbase backend module controllers extend ActionController , just like frontend controllers. The key difference is that instead of $this->view, the controller uses a ModuleTemplate object obtained from ModuleTemplateFactory . The ModuleTemplate provides assign() and renderResponse() methods and wraps the rendered output in the backend page frame:

EXT:my_extension/Classes/Controller/ConferenceController.php
use MyVendor\MyExtension\Domain\Repository\ConferenceRepository;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
    public function __construct(
        protected readonly ModuleTemplateFactory $moduleTemplateFactory,
        protected readonly ConferenceRepository $conferenceRepository,
    ) {}

    public function indexAction(): ResponseInterface
    {
        $moduleTemplate = $this->moduleTemplateFactory->create($this->request);
        $moduleTemplate->assign('conferences', $this->conferenceRepository->findAll());
        return $moduleTemplate->renderResponse('Conference/Index');
    }
}
Copied!

Do not use $this->view in a backend module controller. The $this->view object operates in a frontend context — it lacks the backend link generation, flash message queue, and header components that ModuleTemplate provides.

ModuleTemplateFactory provides the backend page frame, toolbar buttons, flash message area, and navigation components — but only when the Fluid template uses the backend Module Layout. Without it, renderResponse() returns plain rendered HTML with no backend chrome. Using the Module Layout is strongly recommended for any module that should look like a native TYPO3 backend page. See ModuleTemplateFactory for the full API.

How the module configuration is assembled 

When an Extbase backend module handles a request, the framework assembles a single configuration array from two layers, each able to override the previous:

  1. module.tx_myextension — extension-wide defaults, applied to every module of this extension.
  2. module.tx_myextension_mymodule — module-specific values, override the extension-wide layer.

There is no FlexForm layer — backend modules are not content elements and have no pi_flexform record.

The resulting array has three top-level keys that Extbase uses directly:

  • settings — arbitrary key/value pairs available as $this->settings in the controller. ModuleTemplate does not auto-assign {settings} to the template — pass it explicitly with $moduleTemplate->assign('settings', $this->settings) when needed.
  • persistence — controls record loading; the most relevant sub-key is storagePid, which limits which page(s) the repository queries.
  • view — overrides template file resolution via templateRootPaths, layoutRootPaths, and partialRootPaths.