Dokumentation durchblättern
Module entwickeln
Registries-Referenz
Die vollständige Referenz aller Erweiterungs-Registries mit Methoden und Beispielen — von Navigation und Dashboard-Widgets über Benachrichtigungs-Kanäle bis zu Wetter, Speicher, PDF und geplanten Aufgaben.
Die Registries sind das Herz des Modulsystems: Über sie meldet ein Modul seine Fähigkeiten an, ohne den Core anzufassen. Diese Seite ist die Nachschlage-Referenz — Sie müssen sie nicht am Stück lesen, sondern springen zu der Registry, die Sie gerade brauchen.
Alle Erweiterungs-Registries erweitern App\Services\Extension\ExtensionRegistry (oder
folgen deren Muster). Die Basisklasse stellt bereit:
abstract class ExtensionRegistry
{
protected array $items = [];
public function register(string $slug, mixed $entry): void; // Eintrag hinzufügen (warnt bei Überschreiben)
public function resolve(string $slug): mixed; // Eintrag oder null
public function all(): array; // alle Einträge
public function has(string $slug): bool; // Existenz prüfen
public function remove(string $slug): void; // entfernen
}
Alle Registries sind im AppServiceProvider als Singletons registriert. Lösen Sie sie
aus dem Container auf:
$registry = app(NavigationRegistry::class);
// oder per Constructor-Injection in Ihrem ServiceProvider
NavigationRegistry
Klasse: App\Services\Extension\NavigationRegistry
Verwaltet die Navigation der Admin-Seitenleiste.
Methoden
// Eine Navigationsgruppe (Abschnitts-Überschrift) hinzufügen
addGroup(string $key, string $label, int $order = 100): void
// Alle Gruppen nach order sortiert holen
getGroups(): array
// Einen Navigationspunkt hinzufügen
addItem(
string $group, // Gruppen-Key (z. B. 'system', 'stammdaten')
string $slug, // eindeutige Item-Kennung
string $label, // Anzeigetext
string $route, // Laravel-Routenname
string $icon, // ROHE SVG-Pfad-Geometrie (Inhalt von d=), bei mehreren
// Pfaden '||'-getrennt — KEIN 'heroicon-o-*'-Name.
int $order = 100, // Sortierung innerhalb der Gruppe
?string $permission = null, // benötigte Berechtigung
?string $routeCheck = null, // Routenname; Item wird ausgeblendet, falls !Route::has() — unbedingt setzen!
?string $activePattern = null, // Routen-Muster für den Aktiv-Zustand
?string $badge = null, // Badge-HTML/-Text
): void
// Gruppierte Items, gefiltert nach den Berechtigungen des Nutzers
getItems(?User $user = null): array
Core-Navigationsgruppen
| Key | Label | Order |
|---|---|---|
top | Dashboard | 0 |
stammdaten | Stammdaten | 10 |
einsaetze | Einsätze | 20 |
auswertungen | Auswertungen | 30 |
system | System | 40 |
Beispiel
$nav = app(NavigationRegistry::class);
$nav->addItem(
group: 'system',
slug: 'my-module-settings',
label: __('my-module::messages.settings'),
route: 'admin.my-module.settings',
icon: 'heroicon-o-cog',
order: 200,
permission: 'settings.view',
);
Setzen Sie routeCheck: auf den eigenen Routennamen. Ist die Route — etwa weil das Modul
gerade deaktiviert ist — nicht vorhanden, verschwindet der Menüpunkt sauber, statt einen
500-Fehler auszulösen. Warum das gerade beim Routen-Caching wichtig ist, steht unter
Modul-Lebenszyklus.
PortalNavigationRegistry
Klasse: App\Services\Extension\PortalNavigationRegistry
Verwaltet die Navigation des Kundenportals (Desktop- und Mobil-Menü) — das Gegenstück
zur NavigationRegistry für die Kundenseite. Hinzugekommen in 1.1.3.
Unterschiede zur Admin-NavigationRegistry:
- läuft gegen den
customer-Guard. Kunden haben keine Gates/Berechtigungen, daher steuert eine optionalecondition-Closure die Sichtbarkeit, die denCustomererhält. labelspeichert einen Übersetzungs-Key, keinen fertigen Text. Die Portal-Locale wird pro Anfrage (pro Kunde) inEnsureCustomergesetzt — nach dem Boot. Das Layout löst den Key daher erst beim Rendern mit__()auf. (Die Admin-Registry speichert bereits übersetzte Labels.)- kein Icon — Portal-Tabs sind reiner Text.
Methoden
addItem(
string $slug, // eindeutige Item-Kennung
string $label, // ÜBERSETZUNGS-KEY (wird beim Rendern mit __() aufgelöst)
string $route, // Laravel-Routenname, z. B. 'portal.documents.index'
int $order = 100, // Sortierung
?string $activePattern = null, // Routen-Muster für Aktiv-Zustand (Default: $route)
?\Closure $condition = null, // optionale fn(Customer $c): bool — false blendet aus
): void
getItems(?Customer $customer = null): array
Beispiel
$nav = app(PortalNavigationRegistry::class);
$nav->addItem(
slug: 'contracts',
label: 'my-module::portal.nav_contracts', // Übersetzungs-Key
route: 'portal.contracts.index',
order: 25,
activePattern: 'portal.contracts.*',
condition: fn (\App\Models\Customer $c) => true, // optionale Sichtbarkeit pro Kunde
);
Die Items erscheinen automatisch in der Desktop-Navigation und im Mobil-Menü.
LocaleRegistry
Klasse: App\Services\Extension\LocaleRegistry
Registry der verfügbaren UI-Sprachen. Der Core registriert de und en;
Sprachpaket-Module ergänzen weitere Locales (z. B. cs). Hinzugekommen in 1.1.3.
Methoden
add(string $code, string $label): void // Locale registrieren, z. B. add('cs', 'Čeština')
codes(): array // ['de', 'en', ...] — für Validierung (Rule::in)
labels(): array // ['de' => 'Deutsch', ...] — für Sprach-Auswahl
has(string $code): bool // zur Absicherung von App::setLocale()
Beispiel
// In der ServiceProvider::boot() eines Sprachpaket-Moduls
app(LocaleRegistry::class)->add('cs', 'Čeština');
Boot-Zeitpunkt: Modul-Locales werden während ModuleManager::boot() registriert; die
anwendungsweite default_locale wird erst danach angewendet. So kann eine vollständig
tschechische Installation (default_locale = cs) über eine von einem Modul bereitgestellte
Locale aufgelöst werden.
PublicHomepageRegistry
Klasse: App\Services\Extension\PublicHomepageRegistry
Lässt ein Modul die öffentliche Wurzel-URL / übernehmen und dort eine öffentliche
Startseite ausliefern, statt auf den Login umzuleiten. Zugleich ist diese Registry die
einzige Quelle der Wahrheit dafür, welche Seiten Suchmaschinen sehen dürfen. Sie ist die
Grundlage für ein geplantes Frontpage-Modul — die Registry selbst ist vorhanden, das
Modul, das sie befüllt, ist noch nicht verfügbar. Hinzugekommen in 1.1.6.
Methoden
register(callable $handler): void // "/" bedienen; handler liefert Response|View|string. Markiert "/" automatisch als crawlbar.
has(): bool
render(): mixed
allowCrawling(string ...$paths): void // weitere öffentliche Seiten anmelden, z. B. '/leistungen'
crawlablePaths(): array // list<string>
isCrawlable(string $path): bool // Wurzel matcht exakt; Abschnitte matchen Unterpfade, nicht bloße Präfixe
setSitemapUrl(string $url): void // wird in der robots.txt angekündigt (das Modul liefert die Sitemap selbst)
sitemapUrl(): ?string
Beispiel
// In der ServiceProvider::boot() des Frontpage-Moduls
$home = app(PublicHomepageRegistry::class);
$home->register(fn () => view('frontpage::homepage')); // bedient "/"
$home->allowCrawling('/leistungen', '/impressum'); // weitere öffentliche Seiten
$home->setSitemapUrl(url('/sitemap.xml'));
Der Grundgedanke ist Default-Deny: Alles, was nicht ausdrücklich angemeldet wurde, bleibt
privat. Eine Installation legt also nichts versehentlich offen, nur weil ein Modul aktiv ist
— erst register() macht / öffentlich, erst allowCrawling() gibt weitere Pfade frei.
Wichtig ist außerdem das Auflösen zur Anfragezeit: Die /-Route fragt die Registry bei
jedem Aufruf ab, statt das Ergebnis beim Booten festzuschreiben. So übersteht die
Konfiguration auch ein route:cache, das andernfalls eine zur Boot-Zeit getroffene
Entscheidung einfrieren würde.
Hier steht bewusst nur die Registry-API. Das vollständige Indexierungs-Modell — die
robots.txt-Route, der X-Robots-Tag-Header und das <meta name="robots"> — sowie das
Narrativ und die Anleitung zur öffentlichen Startseite liegen im Kapitel
Öffentliche Startseite & SEO. Wie die /-Route in das
übrige Routing eingebettet ist, beschreibt Routen & APIs.
JobTypeRegistry
Klasse: App\Services\Extension\JobTypeRegistry
Macht die Menge der Einsatz- bzw. Tätigkeitstypen erweiterbar. Der Core registriert beim
Booten seine eingebauten JobType-Enum-Fälle; ein Modul ergänzt eigene Typen, ohne den Core
anzufassen. Weil ein Einsatz seinen type als String speichert, braucht ein neuer Typ
keine Migration. Die Monatsstatistik wertet die Einsätze pro Typ aus, sodass ein
modul-eigener Typ ohne weiteres Zutun in den Auswertungen erscheint. Grundlage ist sie unter
anderem für ein geplantes Grünpflege-Modul — die Registry ist vorhanden, das Modul noch
nicht verfügbar. Hinzugekommen in 1.1.6.
Methoden
registerType(string $value, string $labelKey, int $order = 100, ?string $module = null): void
hasType(string $value): bool
values(): array // string[] der Typ-Werte, sortiert
types(): array // App\ValueObjects\JobTypeValue[]
label(string $value): string // übersetztes Label via __() des registrierten label_key
Beispiel
app(JobTypeRegistry::class)->registerType(
value: 'gruenpflege',
labelKey: 'gruenpflege::job.type_gruenpflege',
order: 100,
module: 'gruenpflege',
);
Der labelKey ist absichtlich ein Übersetzungs-Key und kein fertiger Text: label() löst ihn
erst beim Anzeigen mit __() auf, sodass derselbe Typ in jeder UI-Sprache passend erscheint.
Geben Sie module: mit, damit sich der Typ einem Modul zuordnen und beim Entfernen wieder
sauber abräumen lässt.
LifecycleFieldRegistry
Klasse: App\Services\Extension\LifecycleFieldRegistry
Lässt Module zusätzliche Felder in die Fahrer-Lebenszyklus-Abläufe einhängen
(Schichtbeginn/-ende, Einsatzbeginn/-ende) — also modul-eigene Daten erfassen, validieren und
speichern, ohne die Core-Formulare zu patchen. Grundlage ist sie unter anderem für geplante
Lager- und Grünpflege-Module — die Erfassungspunkte existieren, die Module sind noch
nicht verfügbar. Die vier Momente sind das Enum App\Enums\LifecyclePoint. Hinzugekommen in 1.1.6.
| Fall | Wert |
|---|---|
LifecyclePoint::ShiftStart | shift.start |
LifecyclePoint::ShiftEnd | shift.end |
LifecyclePoint::JobStart | job.start |
LifecyclePoint::JobEnd | job.end |
Methoden
registerField(LifecyclePoint $point, string $slug, array $contribution): void
contributions(LifecyclePoint $point, ?Authenticatable $user = null): array // sortiert, nach Berechtigung gefiltert
rules(LifecyclePoint $point, ?Authenticatable $user = null): array // zusammengeführte Validierungsregeln
fieldKeys(LifecyclePoint $point): array // aus dem Request zu lesende Keys
render(LifecyclePoint $point, ?Authenticatable $user = null): string // verkettetes View-HTML
persist(LifecyclePoint $point, Model $entity, array $validated, User $user): void
Contribution-Array
[
'view' => 'lager::fields.salt_used', // ins Formular gerenderte Blade-View (erhält $user)
'rules' => ['lager_salt_used' => 'nullable|numeric|min:0'], // Keys mit Namespace versehen!
'persist' => fn (Model $entity, array $validated, User $user) => /* ... */, // Closure | class-string | LifecycleFieldHandler
'order' => 100,
'permission' => null, // optionales Gate; gilt für render(), rules() UND persist()
]
Rendern — die @lifecycleFields-Direktive
Die Core-Formulare rendern den Einschubpunkt über eine Blade-Direktive:
@lifecycleFields(\App\Enums\LifecyclePoint::ShiftStart)
Beispiel
app(LifecycleFieldRegistry::class)->registerField(
LifecyclePoint::JobEnd,
'lager_salt_used',
[
'view' => 'lager::fields.salt_used',
'rules' => ['lager_salt_used' => 'nullable|numeric|min:0'],
'persist' => \Schneespur\Module\Lager\Lifecycle\RecordSaltUsage::class,
'permission' => 'lager.record',
],
);
Drei Punkte sind in der Praxis entscheidend — und erklären, warum die API so geschnitten ist.
Erstens: Geben Sie Ihren Feld-Keys einen Namespace (lager_salt_used, nicht notes).
Mehrere Module tragen in denselben Lebenszyklus-Moment ein; ihre Beiträge werden
zusammengeführt, und bei gleichem Key gewinnt der letzte. Ein eigener Präfix verhindert, dass
sich zwei Module gegenseitig überschreiben. Zweitens: Ein permission-Key sichert nicht nur
die Anzeige, sondern auch persist() ab — ein Feld, das ein Nutzer nicht sehen darf, kann er
auch nicht schreiben. Drittens: Manuelle Einsätze umgehen die Lebenszyklus-Hooks — die
Felder werden ausschließlich in den Fahrer-Abläufen (Schicht/Einsatz) erfasst.
Die @lifecycleFields-Direktive ist bei den
Frontend-Assets beschrieben; das Interface, das ein
persist-Handler implementiert, finden Sie unter
Interfaces (LifecycleFieldHandler).
DashboardWidgetRegistry
Klasse: App\Services\Extension\DashboardWidgetRegistry
Verwaltet die Karten auf dem Admin-Dashboard.
Methoden
registerWidget(string $slug, array $config): void
// Sichtbare Widgets für einen Nutzer (nach Berechtigung + condition gefiltert, nach order sortiert)
getWidgets(?User $user = null): array
Config-Array
[
'slug' => 'my-widget', // wird aus dem ersten Parameter gesetzt
'label' => 'Widget Title', // Anzeige-Label
'view' => 'my-module::widgets.card', // zu rendernde Blade-View
'dataCallback' => fn () => [...], // optional: Callable, das View-Daten liefert
'order' => 100, // Sortierung (kleiner = weiter oben)
'permission' => 'dashboard.view', // optional: benötigte Berechtigung
'condition' => fn () => true, // optional: Callable, false blendet aus
'size' => 'full', // 'full' oder 'half'
]
Beispiel
$widgets = app(DashboardWidgetRegistry::class);
$widgets->registerWidget('telegram-status', [
'label' => 'Telegram Status',
'view' => 'telegram::widgets.status',
'dataCallback' => fn () => ['connected' => TelegramService::isConnected()],
'order' => 150,
'size' => 'half',
'permission' => 'settings.view',
]);
Das dataCallback wird erst beim Rendern ausgeführt — teure Abfragen laufen also nur, wenn
das Widget für den jeweiligen Nutzer überhaupt sichtbar ist.
FilterRegistry
Klasse: App\Services\Extension\FilterRegistry
Hook-/Filter-System im WordPress-Stil. Registrieren Sie Callbacks auf benannte Hooks; der Core wendet sie an definierten Stellen an.
Methoden
register(string $hook, callable $callback, int $priority = 100): void
apply(string $hook, mixed $value, mixed ...$context): mixed
Priorität
Kleinere Prioritätszahlen laufen zuerst. Bei gleicher Priorität entscheidet die Einfüge-Reihenfolge. Wirft ein Callback eine Ausnahme, wird der vorige Wert wiederhergestellt und eine Warnung protokolliert — ein fehlerhafter Filter kann die Pipeline so nicht zum Absturz bringen.
Die verfügbaren Hooks mit ihren Signaturen sind im Kapitel Filter-Hooks aufgeführt.
SlotRegistry
Klasse: App\Services\Extension\SlotRegistry
Template-Einschub-System — fügt Inhalt an vordefinierten Punkten in den Blade-Layouts ein.
Methoden
// Eine View an einen Slot anhängen (mehrere Anhänge werden der Reihe nach gerendert)
append(
string $slotName,
string $viewPath,
array $data = [],
int $order = 100,
?string $permission = null,
): void
// Einen Slot vollständig ersetzen (bei mehreren gewinnt der letzte)
replace(
string $slotName,
string $viewPath,
array $data = [],
?string $permission = null,
): void
// Den Inhalt eines Slots rendern (von der @extensionSlot-Blade-Direktive aufgerufen)
render(string $slotName, ?Authenticatable $user = null): string
// Alle registrierten Slot-Namen auflisten
getSlotNames(): array
Welche Slot-Namen es je Layout gibt, listet getSlotNames() zur Laufzeit auf; die
verfügbaren Einschubpunkte beschreibt das Kapitel Template-Slots.
PermissionRegistry
Klasse: App\Services\Extension\PermissionRegistry
Registriert Berechtigungen, die Rollen zugewiesen werden können.
Methoden
registerPermission(
string $slug, // z. B. 'my-module.manage'
string $label, // lesbares Label
string $group, // Berechtigungs-Gruppe
?string $module = null, // Modul-Slug (für Aufräumen beim Entfernen)
): void
getPermissions(): array // alle Berechtigungen
getByGroup(string $group): array // nach Gruppe filtern
getByModule(string $module): array // nach Modul filtern
removeByModule(string $module): void // alle eines Moduls entfernen
Beispiel
$permissions = app(PermissionRegistry::class);
$permissions->registerPermission(
slug: 'telegram.manage',
label: 'Manage Telegram settings',
group: 'telegram',
module: 'telegram',
);
Geben Sie module: immer mit — dadurch lassen sich beim Entfernen des Moduls alle seine
Berechtigungen in einem Zug aufräumen.
RoleTemplateRegistry
Klasse: App\Services\Extension\RoleTemplateRegistry
Vordefinierte Rollen-Konfigurationen, die Admins beim Anlegen von Rollen anwenden können.
Methoden
registerTemplate(
string $slug,
string $name,
string $description,
array $permissions, // Array von Berechtigungs-Slugs
?string $module = null,
): void
getTemplates(): array
getByModule(string $module): array
removeByModule(string $module): void
Beispiel
$templates = app(RoleTemplateRegistry::class);
$templates->registerTemplate(
slug: 'accountant',
name: 'Buchhaltung',
description: 'Zugriff auf Dokumente und Rechnungen',
permissions: ['documents.view', 'invoices.view', 'invoices.export'],
module: 'documents',
);
DispatchStrategyRegistry
Klasse: App\Services\Extension\DispatchStrategyRegistry
Verwaltet Algorithmen zur Einsatz-Zuteilung.
Methoden
register(string $slug, string $class): void // class-string<DispatchStrategyInterface>
resolve(?string $slug = null): DispatchStrategyInterface // aus dem Container; Fallback 'manual'
availableStrategies(): array // array<string, array{name: string}>
activeSlug(): string // aktuell konfigurierte Strategie
Die aktive Strategie liegt in der Einstellung dispatch_strategy. Default ist 'manual'.
NotificationChannelRegistry
Klasse: App\Services\Notification\NotificationChannelRegistry
Verwaltet Benachrichtigungs-Kanäle (E-Mail, Telegram, SMS usw.).
Methoden
register(string $slug, string $channelClass): void // class-string<NotificationChannelInterface>
// Benachrichtigung an alle aktivierten Kanäle senden (mit Filter-Hook)
dispatch(Job $job, string $type, array $context): array
// Instanziierte, aktivierte Kanäle holen
enabledChannels(): array // array<string, NotificationChannelInterface>
dispatch() wendet den Filter schneespur.job.notification.channels an — Module können
darüber beeinflussen, welche Kanäle eine bestimmte Benachrichtigung erhalten.
TwoFactorMethodRegistry
Klasse: App\Services\Extension\TwoFactorMethodRegistry
Verwaltet Verfahren zur Zwei-Faktor-Authentifizierung.
Methoden
registerMethod(string $slug, string $methodClass): void // class-string<TwoFactorMethodInterface>
getMethods(): array // alle registrierten Klassen
getAvailableMethods(Container $container): array // instanziierte Methoden
getByModule(string $module): array // nach Modul-Namespace filtern
removeByModule(string $module): void
BackupTargetRegistry
Klasse: App\Services\Backup\BackupTargetRegistry
Verwaltet Backup-Speicherziele.
Methoden
register(string $slug, string $class): void // class-string<BackupTargetInterface>
resolve(?string $slug = null): BackupTargetInterface // Fallback 'local'
availableTargets(): array // array<string, array{label, configured}>
activeSlug(): string
StorageBackendRegistry
Klasse: App\Services\Storage\StorageBackendRegistry
Verwaltet Datei-Speicher-Backends mit automatischem Rückfall auf den lokalen Speicher.
Methoden
register(string $slug, string $class): void // class-string<StorageBackendInterface>
resolve(?string $slug = null): StorageBackendInterface
availableBackends(): array // array<string, array{label, configured}>
activeSlug(): string
// Lesen mit automatischem Rückfall auf lokal, falls das aktive Backend nichts findet
retrieveWithFallback(string $relativePath): ?string
// URL mit automatischem Rückfall auf lokal
urlWithFallback(string $relativePath): string
Der eingebaute Fallback ist der Grund, warum eine vorübergehend nicht erreichbare Remote-Ablage nicht sofort zu fehlenden Dateien führt — gelesen wird notfalls aus dem lokalen Speicher.
WeatherProviderRegistry
Klasse: App\Services\Weather\WeatherProviderRegistry
Verwaltet Wetter-Datenquellen.
Methoden
register(string $slug, string $class): void // class-string<WeatherProviderInterface>
resolve(?string $slug = null): WeatherProviderInterface
availableProviders(): array // array<string, array{name, requires_api_key}>
activeSlug(): string
PdfRendererRegistry
Klasse: App\Services\Pdf\PdfRendererRegistry
Verwaltet PDF-Engines (Standard: DomPDF).
Methoden
register(string $slug, string $class): void // class-string<PdfRendererInterface>
resolve(?string $slug = null): PdfRendererInterface
ReportFormatRegistry
Klasse: App\Services\Report\ReportFormatRegistry
Verwaltet Export-Formate (PDF, CSV und eigene Formate).
Methoden
register(string $slug, string $class): void // class-string<ReportFormatInterface>
resolve(string $slug): ?ReportFormatInterface
availableFormats(): array
ScheduledTaskRegistry
Klasse: App\Services\Scheduler\ScheduledTaskRegistry
Verwaltet Cron-Aufgaben.
Methoden
register(string $slug, string $class): void // class-string<ScheduledTaskInterface>
resolve(string $slug): ?ScheduledTaskInterface
enabledTasks(): array // instanziierte, aktivierte Aufgaben
recordRun(string $slug, string $status, ?string $error, int $durationMs): void
lastRun(string $slug): ?object // letzter Ausführungs-Datensatz
allWithStatus(): array // alle Aufgaben mit ihrem letzten Lauf
DiagnosticReporterRegistry
Klasse: App\Services\Diagnostic\DiagnosticReporterRegistry
Verwaltet Backends fürs Fehler-/Crash-Reporting.
Methoden
register(string $slug, string $class): void // class-string<DiagnosticReporterInterface>
Der DiagnosticManager verteilt an alle aktivierten Reporter. Die Payloads werden vor dem
Versand vom DiagnosticPayloadSanitizer bereinigt — sensible Felder verlassen die
Installation also nicht ungefiltert.
ModuleAssetRegistry
Klasse: App\Services\Extension\ModuleAssetRegistry
Verwaltet CSS-/JS-Assets aus Modulen.
Methoden
registerAssets(string $slug, string $modulePath): void // liest dist/manifest.json
getCss(): string[] // URLs aller registrierten CSS-Dateien
getJs(): string[] // URLs aller registrierten JS-Dateien
all(): array // alle Assets mit Typ, URL, Slug
ModuleApiRegistrar
Klasse: App\Services\Extension\ModuleApiRegistrar
Erstellt präfixierte, authentifizierte API-Routengruppen für Module.
Methoden
routes(string $slug, int $version, Closure $callback): void
Legt Routen unter /api/mod/{slug}/v{version}/ an, mit der Middleware module.api:{slug}
und dem Routennamen-Präfix module.{slug}.api.v{version}..
Ein konkretes Modul, das Navigation, Dashboard-Widget, Einstellungen und Routen zusammen nutzt, bauen Sie im Schnelleinstieg.