Den Seitenmodul-Header zähmen — Warum wir EXT:page_info_tabs entwickelt haben

|David Steeb
Vier Aktenordner, die ein Balkendiagramm mit orangefarbenen Balken zeigen, vor einem hellblauen Hintergrund mit abstrakten Dokumentumrissen.

Wer regelmäßig mit TYPO3-Installationen arbeitet, in denen mehrere Extensions im Einsatz sind, kennt die Situation: Der Header des Seitenmoduls kann schnell zu einer wachsenden Ansammlung von Inhalten aus unterschiedlichsten Quellen werden — Aufrufstatistiken, Blog-Metadaten, SEO-Übersichten — alles untereinander gerendert, ohne visuelle Trennung oder Struktur.

Solange nur eine Extension Inhalte zum Header beiträgt, sieht alles ordentlich aus. Doch sobald eine zweite oder dritte Extension hinzukommt, verwandelt sich der Seitenmodul-Header in eine unstrukturierte HTML-Wand. Die benötigten Informationen zu finden bedeutet dann, sich durch Inhaltsblöcke zu scrollen, die nie dafür gedacht waren, nebeneinander zu existieren.

Genau solche kleinen, aber wirkungsvollen Probleme lösen wir bei b13 besonders gern: eine fokussierte, in sich geschlossene Funktion, die den redaktionellen Alltag verbessert — ganz ohne Änderungen an bestehenden Extensions. Deshalb haben wir EXT:page_info_tabs entwickelt.

Grafik, die die Website-Traffic-Statistiken der letzten 30 Tage anzeigt, mit Daten, die nach Typ und Sprache segmentiert sind. Zusammenfassung der Artikeldetails unten.

Das Problem: Eine wachsende Ansammlung zusammenhangloser Inhalte

TYPO3 bietet einen sauberen Mechanismus, mit dem Extensions Inhalte zum Seitenmodul-Header hinzufügen können: das Event ModifyPageLayoutContentEvent und dessen Methode addHeaderContent(). Das ist gut durchdacht und funktioniert perfekt — solange nur eine Extension es nutzt.

In der Realität der meisten Projekte sieht es jedoch anders aus. Sobald mehrere Extensions Inhalte beisteuern — und das tun sie zunehmend –, entsteht ein vertikaler Stapel unzusammenhängender HTML-Blöcke. Es gibt keine eingebaute Möglichkeit, diese Bereiche zu trennen, zu beschriften oder zu strukturieren.

In einem aktuellen Projekt hatten wir mehrere Extensions, die Inhalte zum Seitenmodul-Header beitrugen: eine Blog-Extension mit Beitragsmetadaten, ein View-Tracker mit Seitenstatistiken, ein SEO-Tool mit Optimierungshinweisen, eine Übersetzungsübersicht sowie projektspezifische Zusatzinformationen. Das Ergebnis war ein Header-Bereich, durch den Redakteur:innen erheblich scrollen mussten, bevor sie überhaupt beim eigentlichen Seiteninhalt ankamen.

Das Kernproblem ist struktureller Natur: TYPO3 sammelt alle Header-Inhalte in einer einzigen Ausgabe. Es gibt kein Konzept von Abschnitten, Gruppierung oder Navigation. Jede Extension hängt ihr HTML einfach an — und das Ergebnis ist das, was zufällig dabei herauskommt.

Wie EXT:page_info_tabs funktioniert

Die Grundidee von page_info_tabs ist bewusst einfach: Inhalte des Seitenmodul-Headers werden automatisch in Bootstrap-5-Tabs organisiert — ohne dass bestehende Extensions angepasst werden müssen.

Die Extension arbeitet mit dem Decorator-Pattern und dekoriert das EventDispatcherInterface von TYPO3. Sie fängt die Inhalte ab, die einzelne Listener des ModifyPageLayoutContentEvent hinzufügen, und verwandelt die Ausgabe jedes Listeners in einen eigenen Tab. Das ist die zentrale Designentscheidung: Keine Extension muss von page_info_tabs wissen. Keine Code-Anpassungen, keine zusätzlichen Event-Listener, keine Konfiguration in Drittanbieter-Extensions.

Das Verhalten passt sich automatisch an die vorhandene Situation an:

  • 0 Abschnitte — Es wird nichts gerendert
  • 1 Abschnitt — Der Inhalt wird direkt ausgegeben, ohne Tabs (keine unnötige UI)
  • 2+ Abschnitte — Bootstrap-5-Tabs, sortiert nach konfigurierbarer Priorität

Die Tab-Beschriftungen werden automatisch anhand typischer HTML-Muster im Output der jeweiligen Extension erkannt. Die Extension sucht nach CSS-Klassen wie blog-pageheadertx-ext-key oder data-extension-Attributen. Dadurch erhalten die meisten Extensions sofort eine sinnvolle Beschriftung — ganz ohne Konfiguration.

Da das TYPO3-Backend bereits das JavaScript für Bootstrap-Tabs lädt, ist kein zusätzliches JS für das Umschalten erforderlich. Ein kleiner Resize-Event-Helper behebt Darstellungsprobleme bei Chart-Bibliotheken (z. B. Frappe Charts, Chart.js), die in initial versteckten Tab-Panes falsch rendern. Außerdem wird der zuletzt verwendete Tab in localStorage gespeichert, sodass Redakteuren beim Wechsel zwischen Seiten automatisch zur zuletzt genutzten Ansicht zurückkehren.

Grafik, die die Website-Statistiken der letzten 30 Tage anzeigt, mit Daten zu den Aufrufen in Englisch und Deutsch, die Trends bei den Seitenbesuchen hervorhebt.

Entwickelt für Stabilität mit unbekanntem Drittanbieter-Code

Eine der größten Herausforderungen bei einer solchen Extension ist, dass sie zuverlässig mit Inhalten beliebiger Drittanbieter-Extensions funktionieren muss — mit HTML-Strukturen, CSS-Klassen und JavaScript-Verhalten, die vollständig außerhalb unserer Kontrolle liegen.

Deshalb haben wir uns bewusst für das Decorator-Pattern entschieden. EXT:page_info_tabs verändert, überschreibt oder manipuliert das HTML anderer Extensions nicht. Jede Ausgabe wird lediglich in ein Tab-Panel eingebettet. Der Inhalt innerhalb des Tabs ist exakt das, was die ursprüngliche Extension gerendert hat — unverändert.

Dieses Design stellt sicher, dass:

  • bestehende Extensions unverändert weiter funktionieren
  • JavaScript-Initialisierungen von Drittanbieter-Extensions intakt bleiben
  • CSS-Scoping erhalten bleibt (keine Klassennamens-Konflikte)
  • bei Deinstallation von page_info_tabs alles automatisch auf das Standard-Stapelverhalten zurückfällt

Dieser Ansatz entspricht unserer Philosophie bei b13: kleine, fokussierte Extensions bauen, die ein klar definiertes Problem lösen, den Umfang begrenzen, minimale Konfiguration erfordern und sich sauber ins Gesamtsystem einfügen. Eine Extension, die Drittanbieter-Inhalte organisiert, muss besonders vorsichtig sein, nichts zu beschädigen.

Installation

Die Installation erfolgt wie gewohnt via Composer:

composer require b13/page-info-tabs

Das war’s. Alle bestehenden Extensions, die addHeaderContent() verwenden, erhalten automatisch ihren eigenen Tab. Zusätzliche Konfiguration ist nicht erforderlich.

Labels und Prioritäten konfigurieren

Für bekannte Extensions sind Standard-Labels hinterlegt. Die automatische Erkennung funktioniert in den meisten Setups zuverlässig, kann aber bei Bedarf explizit angepasst werden.

Um Labels anzupassen oder hinzuzufügen, legen Sie diese in Ihrer ext_localconf.php oder AdditionalConfiguration.php fest:

$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['page_info_tabs']    ['labels']['view_tracker'] = 'Page Views';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['page_info_tabs']    ['labels']['blog'] = 'Blog';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['page_info_tabs']    ['labels']['my_extension'] = 'My Label';

Prioritäten steuern die Tab-Reihenfolge (kleiner Wert = weiter links):

$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['page_info_tabs']    ['priorities']['view_tracker'] = 20;
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['page_info_tabs']    ['priorities']['blog'] = 10;

Den richtigen Extension-Key finden

Jedes Tab-Panel enthält einen HTML-Kommentar mit dem erkannten Key. Öffnen Sie die Developer-Tools Ihres Browsers und inspizieren Sie den Tab-Inhalt:

<!-- page-info-tabs key: view_tracker -->

Diesen Key verwenden Sie anschließend für Label- und Prioritäts-Konfiguration.

Die automatische Erkennung erfolgt in folgender Reihenfolge:

  1. data-extension="my_ext" Attribut (am zuverlässigsten)
  2. CSS-Klassen wie my-ext-pageheader oder my-ext-widget
  3. TYPO3-Konventionen: tx-my-ext oder tx_my_ext
  4. b13-JS-Hooks: bJS_txMyExt
  5. EXT:my_ext/-Referenzen in src/href-Attributen

Falls die Auto-Erkennung einen unerwarteten Key liefert, können Sie entweder direkt ein Label für diesen Key konfigurieren oder die Extension-Autoren bitten, ein data-extension-Attribut hinzuzufügen.

Explizite Section-Registrierung (optional)

Extensions, die vollständige Kontrolle über Label, Priorität und Inhalt ihres Tabs wünschen, können stattdessen auf CollectPageInfoSectionsEvent reagieren. Explizit registrierte Sections haben Vorrang vor automatisch erfassten Inhalten derselben Extension.

use B13\PageInfoTabs\Event\CollectPageInfoSectionsEvent;
use B13\PageInfoTabs\Model\Section;
use TYPO3\CMS\Core\Attribute\AsEventListener;

#[AsEventListener]
final class MyPageInfoSection{    
  public function __invoke(        
    CollectPageInfoSectionsEvent $event    
  ): void {
    $event->addSection(
      new Section(            
        identifier: 'my-extension',            
        label: 'My Label',            
        content: '<div>Your HTML here</div>',            
        priority: 50,        
      )
    );    
  }
}

Diese API ist bewusst einfach gehalten: ein Event, ein Value Object und klare Prioritätsregeln. Extension-Entwickler:innen können sie in wenigen Minuten integrieren.

Fazit

EXT:page_info_tabs ist eine kleine Extension, die ein echtes Alltagsproblem im TYPO3-Backend löst. Sie nimmt Inhalte beliebig vieler Drittanbieter-Extensions — Inhalte, die nie für ein gemeinsames Auftreten konzipiert wurden — und organisiert sie in einer klaren, navigierbaren Tab-Struktur.

Was diese Extension besonders macht, ist das, was sie nicht benötigt: keine Anpassungen bestehender Extensions, keine komplexe Konfiguration, kein zusätzliches JavaScript. Installieren — und der Seitenmodul-Header ist sofort strukturiert.

Genau solche Extensions möchten wir bei b13 bauen: fokussiert auf ein klar definiertes Problem. Klein genug, um langfristig wartbar zu bleiben. Stabil genug, um zuverlässig mit unbekanntem Drittanbieter-Code zu funktionieren. Und so konzipiert, dass sie sofort einsatzbereit sind — bei Bedarf aber flexibel konfigurierbar bleiben.

Dokumentation und Quellcode sind auf GitHub verfügbar:

Neugierig geworden?

In größeren TYPO3-Installationen mit vielen Extensions im Seitenmodul macht ein strukturierter Header einen spürbaren Unterschied im redaktionellen Workflow.

Wenn du Unterstützung bei der Einführung von EXT:page_info_tabs oder der Integration in ein bestehendes TYPO3-Projekt benötigst, sprich uns gern an.