Create a backend module with Extbase 

A backend module can be built with Extbase and Fluid. The module's controller is an Extbase ActionController , and the domain models, repositories and validators of the extension work in the module as they do in a frontend plugin. This is the better choice when the module works with a domain model of its own.

An Extbase controller needs no attribute. Every class implementing ControllerInterface is tagged and made public automatically. The AsController attribute is only for backend controllers without Extbase.

Changed in version 14.0 Breaking: #105377 - Deprecated functionality removed

The class alias for \TYPO3\CMS\Backend\Attribute\Controller has been removed. \TYPO3\CMS\Backend\Attribute\AsController is still in place.

Building such a module is described in a dedicated chapter:

Fluid templates of an Extbase backend module 

A module template uses the Module layout and puts its content into the Content section. The layout belongs to the backend, not to the extension.

ModuleTemplate looks for templates and layouts in EXT:backend/Resources/Private/ first, and in the extension that registered the module second. That is why <f:layout name="Module" /> finds the backend's Layouts/Module.fluid.html without any configuration. ModuleTemplate also supplies the document header and flash messages the layout renders:

EXT:my_extension/Resources/Private/Templates/ConferenceModule/List.fluid.html
<html
  xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
  data-namespace-typo3-fluid="true">

<f:layout name="Module" />

<f:section name="Content">
  <f:asset.module identifier="@typo3/backend/modal.js" />

  <h1>Conferences</h1>

  <f:form action="list" name="demand" object="{demand}">
    <f:form.textfield property="searchWord" placeholder="Search" />
    <f:form.select
      property="status"
      options="{published: 'Published', unpublished: 'Unpublished'}"
      prependOptionLabel="All"
      prependOptionValue=""
    />
    <f:form.submit value="Filter" />
    <f:link.action action="list" arguments="{operation: 'reset-filters'}">
      Reset filters
    </f:link.action>
  </f:form>

  <be:link.newRecord
    table="tx_myextension_domain_model_conference"
    pid="{newRecordPid}"
  >
    New conference
  </be:link.newRecord>

  <table class="table table-striped">
    <f:for each="{paginator.paginatedItems}" as="conference">
      <tr>
        <td>
          <be:link.editRecord
            table="tx_myextension_domain_model_conference"
            uid="{conference.uid}"
            fields="title"
            contextual="true"
          >
            {conference.title}
          </be:link.editRecord>
        </td>
        <td>
          <div class="btn-group">
            <be:link.editRecord
              table="tx_myextension_domain_model_conference"
              uid="{conference.uid}"
              class="btn btn-default"
            >
              Edit
            </be:link.editRecord>
            <a
              href="{be:moduleLink(
                route: 'tce_db',
                query: 'cmd[tx_myextension_domain_model_conference][{conference.uid}][delete]=1',
                currentUrlParameterName: 'redirect'
              )}"
              class="btn btn-default t3js-modal-trigger"
              data-severity="warning"
              data-title="Delete conference"
              data-content="This conference will be deleted."
              data-button-close-text="Cancel"
              data-button-ok-text="Delete"
            >
              Delete
            </a>
          </div>
        </td>
      </tr>
    </f:for>
  </table>

  <nav aria-label="Pagination">
    <f:for each="{pagination.allPageNumbers}" as="page">
      <f:link.action action="list" arguments="{currentPage: page}">
        {page}
      </f:link.action>
    </f:for>
  </nav>
</f:section>

</html>
Copied!

The same layout serves modules without Extbase. Buttons, menus and the breadcrumb in the document header are not Extbase-specific either, see Button components and DocHeaderComponent.

The best way to learn more is to read the modules that ship with TYPO3. The backend user module ( typo3/cms-beuser ) and the log module ( typo3/cms-belog ) are built with Extbase.