Frontend manifest
Overview
The manifest is the only way a plugin contributes user interface: one file frontend/plugin.manifest.ts with a default export. There are 26 keys — navigation, routes, widgets, settings tiles, extension points, overrides and translations.
The interface build merges the manifests of all active plugins; a disabled plugin contributes nothing.
The explanations below come verbatim from the contract in the code and are therefore in German.
Keys
| Key | Required | Meaning | |
|---|---|---|---|
routes | no | Authentifizierte Staff-Routen (gemergt in die AppLayout-Children). | |
nav | no | Eigene, neue Nav-Gruppen (ans Ende angehängt; Nutzer sortiert via navOrder um). | |
routeModules | no | SPA-Route-Präfix → module.*-Kurz-Key (fail-closed Modul-Gating). | |
apiSegmentModules | no | /api/v1/<segment> → module.*-Kurz-Key für Plugin-API-Segmente, die geteilte Core-Bausteine (Timeline, Widgets, Picker) optional konsumieren. Frontend-Pendant zu Backend-getRouteSegments(): Core fragt moduleForApiPath() statt Segmente zu kennen, Aufruf unterbleibt bei deaktiviertem Modul (fail-closed) statt 404. Kollision → Core gewinnt, dann first-wins (warn). | |
editorExtensions | no | Tiptap-Blocktypen für den Pages-Editor (Doc 17 §5). | |
locales | no | Übersetzungen je Sprache, Struktur wie Core-Locale-Datei ({ <namespace>: { … } }). Additiv tief gemergt; Konflikt → Core gewinnt (warn). Schlüssel = Locale-Code, bewusst string statt `'de' \ | 'en' (Sprachpaket-Ausbau 2026-07-17) — auch für per Sprachpaket nachgelieferte Sprachen. Codes ohne registrierte Sprache werden ignoriert. BEVORZUGT ist {@link localeLoaders} (Systemaudit R32). Dieses Feld bleibt gültig und funktionsfähig — ein Fremd-Plugin älterer Fassung bricht nicht —, hat aber einen Preis: es trägt die Nachrichten als WERT, also muss das Manifest sie statisch importieren. Manifeste werden über virtual:octibiz-plugin-contributions` eager eingezogen; damit landet jede Sprache jedes Plugins im Einstiegs-Chunk der SPA, obwohl ein Nutzer genau eine benutzt. |
localeLoaders | no | Übersetzungen je Sprache als LADER — der bevorzugte Weg (Systemaudit R32): localeLoaders: { de: () => import('./locales/de'), en: () => import('./locales/en') } Inhaltlich identisch zu {@link locales} (Struktur { <namespace>: { … } }, additiv tief gemergt, Konflikt → Core gewinnt mit Warnung) — nur wird je Sprache ein eigener Chunk erzeugt und erst geladen, wenn die Sprache wirklich gebraucht wird. Der statische Import muss dafür VERSCHWINDEN: bleibt er stehen, hängt der Sprachbaum weiterhin am Manifest und damit am Einstieg, egal was hier deklariert ist (Wächter: src/__tests__/pluginLocaleLoaders.spec.ts). Beide Felder dürfen nebeneinander stehen (Migration in Schritten); ein Sprach-Code sollte jedoch nur in einem der beiden vorkommen — sonst gewinnt der zuerst gemergte Beitrag (Lader vor locales) und der zweite wird als Kollision verworfen. | |
localeDefinitions | no | SPRACHPAKETE: neue Sprachen fürs Gesamtsystem (Sprachpaket-Ausbau 2026-07-17). Gegenstück zu locales (dort BESTEHENDE Sprache erweitert, hier NEUE Sprache samt Metadaten/Grundübersetzung). - Code darf keine registrierte Sprache doppeln (Core-Ordner gewinnt, Paket verworfen mit Warnung). - Fehlende Schlüssel fallen auf {@link DEFAULT_LOCALE} zurück — unvollständiges Paket bootet, zeigt Lücken deutsch. - Bleibt bewusst INLINE (messages als Wert): ein Paket ist je Definition GENAU EINE Sprache, gemergt wird ohnehin nur die geladene — das Gewichts-Problem der eager locales (jede Sprache jedes Plugins im Einstieg) entsteht hier nicht im selben Maß. Ein Sprachpaket KÖNNTE seine Nachrichten ebenfalls lazy liefern; das ist ein späterer Zugang, heute nicht vorgesehen. | |
navLinks | no | Links in BESTEHENDE Nav-Gruppen (Gegenstück zu nav für neue Gruppen). | |
settingsTiles | no | Settings-Kacheln (inkl. Breadcrumb/Suche/Deep-Link-Modul-Gating aus einer Quelle). | |
areas | no | Bereichsfarbe/Eyebrow der eigenen Nav-Gruppe(n) (statt Indigo-Fallback + „Übersicht"). | |
areaMatches | no | Pfad-Präfixe für einen BESTEHENDEN Bereich: AreaDef.key → Präfixe (z. B. { documents: ['/quotes'] }). Plugin in geteiltem Bereich (Beleg-Kette, Katalog, Finanzen) trägt Pfade selbst bei — Core config/areas.ts kennt keine Plugin-Pfade mehr (G3-Entkopplung 2026-07-13). Unbekannter Key/ vergebener Präfix → verworfen (warn, first-wins, nie throw). | |
widgets | no | Dashboard-Widgets fürs Home-Dashboard (Katalog-Einträge + optionale Kategorien). | |
publicRoutes | no | Öffentliche (login-freie) Top-Level-Routen (Buchung/Formular/Freigabe). meta.public: true erzwungen, vor dem Catch-all registriert. | |
portalRoutes | no | Routen im Kundenportal-Realm (Kinder von /portal, erben die Portal-Auth). | |
portalNav | no | Navigationseinträge des Kundenportals (vor Assistent/Profil eingefügt). | |
portalNotificationTargets | no | Zielauflösung für Portal-Benachrichtigungen (Deep-Link je targetType, Programm 21 AP 5.8). | |
viewExtensions | no | Beiträge zu benannten Extension-Slots in Core-Views (<PluginSlot name="…">). | |
columnExtensions | no | Zusätzliche SPALTEN für AppTable-/ResourceList-Listen (Slot <liste>.columns): Slot-Name → Spalten- Definitionen, gerendert nach Kern-Spalten (permission-/modul-gegated). Für ZEILEN-AKTIONEN genügt eine viewExtensions-Komponente (<liste>.row-actions, je Zeile mit { row }). | |
filterExtensions | no | Zusätzliche FILTER für AppTable-/ResourceList-Listen (Slot <liste>.filters, Spiegel von columnExtensions): Slot-Name → Filter-Definitionen, angehängt NACH Kern-Filtern ({@link PluginFilterExtension}). | |
viewOverrides | no | OVERRIDE-/REPLACE-Beiträge: VERDECKEN/ERSETZEN einer Core-UI-Stelle (Slot, Kern-Spalte, Route) — je target autoritativ (first-wins + warn), verdrängt additive Beiträge ({@link PluginViewOverride}). | |
portalViewExtensions | no | Beiträge zu Extension-Slots in PORTAL-Views (<PortalPluginSlot name="…">) — ohne Staff- Permission-/Modul-Gate; gaten sich reaktiv über den eigenen Portal-API-Call ({@link PluginPortalViewExtension}). | |
searchTypes | no | Treffertypen der zentralen Suche (entityType → Label/Icon/Detail-Route, SearchView). | |
tagScopes | no | Tag-Scope-Beiträge (Einstellungen → Tags): eigene Fachobjekte als Tag-Ziele, modul-gegated. | |
automationActionFields | no | Feld-Schemata für Automations-Actions: Plugin liefert Felder eigener Actions oder hängt sie an eine Core-Action an (appendTo) — statt Core-Hardcoding. Enablement-gefiltert über module ({@link PluginAutomationActionContribution}). | |
commands | no | Befehle für ⌘K-Palette und globales „+ Neu" (Programm 21 D2/AP 2.2) — die Fläche, über die ein Plugin seinen Anlegen-Weg beiträgt, OHNE config/quickCreate.ts im Kern zu editieren. |