b2in/dev/flux-cms/PLAN.md
2026-04-10 17:18:17 +02:00

19 KiB
Raw Permalink Blame History

Flux CMS Integration Entwicklungsplan

Ziel: Integration des flux-cms Packages für die b2in-Webseite.
Scope: Nur b2in weitere Subseiten (b2a, stileigentum, style2own) folgen später.
Stand: 2026-03-18


Ausgangslage

Was existiert

  • Package: packages/flux-cms/ (core, components, starter-components) liegt im Projekt
  • Composer: packages/*/* Repository-Pfad ist in composer.json konfiguriert
  • Frontend: Vollständige b2in-Webseite mit ~15 Seiten
  • Content-Quelle: config/content.php statische PHP-Arrays pro Theme
  • Content-Zugriff: Livewire-Sections laden via config("content.themes.{$theme}.{$section}")
  • Immobilien/Projekte: Komplett in config/content.php definiert (Slug, Titel, Preise, Galerie, Quick Facts, Investment Case, Location etc.), Route immobilien/{slug} liest direkt aus Config
  • Admin-Portal: portal.b2in.test mit eigenem CMS (Cabinets/Displays), User-/Partner-Management
  • Domain-System: Multi-Domain-Setup in config/domains.php

Was fehlt

  • flux-cms/core ist nicht als Composer-Dependency installiert
  • Keine app/helpers.php mit cms()/tcms()/cms_media_url()
  • Keine config/flux-cms.php publiziert
  • Keine flux_cms_* Datenbanktabellen
  • Keine Admin-Views/Routes für das CMS
  • Keine Medienbibliothek
  • Kein Immobilien-Model (Projekte leben in Config)

Scope-Einschränkung Phase 1

Nur diese Tabellen werden initial benötigt:

  • flux_cms_contents Alle Seiteninhalte (Key-Value mit Übersetzungen)
  • flux_cms_media Medienbibliothek (Bilder, PDFs)

Nicht benötigt (kommt später bei Bedarf):

  • flux_cms_news_items Nachrichteneinträge
  • flux_cms_industries Branchen
  • flux_cms_faqs FAQ-Einträge
  • flux_cms_downloads Downloads
  • flux_cms_linkedin_posts LinkedIn-Posts
  • flux_cms_search_index Suchindex

Zusätzlich benötigt:

  • Neues Immobilien/Projekte-Model mit eigenem CRUD im CMS-Backend (ersetzt die statischen Projekte aus config/content.php)

Phasen-Übersicht

Phase Beschreibung Abhängig von
1 Package-Installation & Infrastruktur
2 Immobilien-Model & CRUD Phase 1
3 Content-Migration (config → DB) Phase 1
4 CMS Admin-Backend Phase 1
5 Frontend-Umstellung (config → cms) Phase 2, 3
6 Medienbibliothek & Bilder Phase 1, 4
7 Tests Phase 26
8 Feinschliff & Dokumentation Phase 57

Phase 1 Package-Installation & Infrastruktur

1.1 Composer-Dependency installieren

composer require flux-cms/core:@dev
composer require intervention/image

Prüfen:

  • FluxCmsServiceProvider wird automatisch geladen
  • Keine Konflikte mit bestehenden Dependencies

1.2 Konfiguration publizieren

php artisan vendor:publish --tag=flux-cms-config

Anpassen in config/flux-cms.php:

  • default_locale'de'
  • locales['de' => 'Deutsch', 'en' => 'English']
  • media.profiles → an b2in-Bildgrößen anpassen
  • routes.enabledfalse (eigene Admin-Routes im Portal)

1.3 Migrations ausführen

Nur die benötigten Migrations:

  • create_flux_cms_contents_table
  • create_flux_cms_media_table

Die restlichen Migrations (news, industries, faqs, downloads, linkedin, search_index) werden nicht ausgeführt sie liegen im Package und können bei Bedarf später migriert werden.

Optionen:

  • A) Alle Migrations laufen lassen (Tabellen existieren, werden aber nicht genutzt) einfacher
  • B) Nur selektiv migrieren sauberer, erfordert ggf. Anpassung am ServiceProvider

Empfehlung: Option A leere Tabellen stören nicht und vereinfachen spätere Erweiterung.

php artisan migrate

1.4 Helper-Funktionen einrichten

Erstellen: app/helpers.php mit cms(), tcms(), cms_media_url(), media_url()

Registrieren in composer.json:

"autoload": {
    "files": ["app/helpers.php"]
}
composer dump-autoload
php artisan storage:link

Ergebnis Phase 1: Package installiert, DB-Tabellen vorhanden, Helper verfügbar.


Phase 2 Immobilien/Projekte-Model & CRUD

2.1 Datenstruktur analysieren

Aktuelle Projekt-Daten aus config/content.php (am Beispiel Azizi Creek Views 4):

Feld Typ Beispiel
slug string azizi-creek-views-4
title string Azizi Developments: Creek Views 4
location string Al Jaddaf, Dubai
status string NEW LAUNCH
launch_date string 03.03.2026
price_from integer (AED) 1125000
image string (Pfad) expose/a1/image-4.jpeg
highlights array<string> ['Prime Waterfront Views', ...]
quick_facts array<{icon, label, value}> Typen, Größe, Einheiten, Entwickler
investment_case object {title, text, views[]}
gallery array<string> Bildpfade
location_info object {title, map_url, points[]}
contact object {title, subtitle, options[]}

2.2 Migration erstellen

Neue Migration create_cms_projects_table:

Schema::create('cms_projects', function (Blueprint $table) {
    $table->id();
    $table->string('slug')->unique();
    $table->json('title');            // translatable
    $table->json('location');         // translatable
    $table->string('status')->nullable();
    $table->date('launch_date')->nullable();
    $table->unsignedInteger('price_from_aed')->nullable();
    $table->string('currency')->default('AED');
    $table->string('image')->nullable();        // CmsMedia Referenz
    $table->json('highlights')->nullable();     // translatable array
    $table->json('quick_facts')->nullable();    // [{icon, label, value}]
    $table->json('investment_case')->nullable(); // {title, text, views[]}
    $table->json('gallery')->nullable();        // [filename, ...]
    $table->json('location_info')->nullable();  // {title, map_url, points[]}
    $table->json('contact')->nullable();        // {title, subtitle, options[]}
    $table->boolean('is_published')->default(false);
    $table->unsignedInteger('order')->default(0);
    $table->timestamps();
});

2.3 Model erstellen

App\Models\CmsProject mit:

  • HasTranslations (Spatie) für title, location, highlights
  • Scopes: published(), ordered()
  • toFrontendArray() → kompatibles Array für bestehende Blade-Views
  • getFormattedPrice() → nutzt PriceHelper::formatAed()
  • Accessors für gallery_urls, image_url etc.

2.4 Factory & Seeder

  • Factory: CmsProjectFactory für Tests
  • Seeder: CmsProjectSeeder importiert die bestehenden Projekte aus config/content.php in die DB

2.5 Admin CRUD (Volt-Komponente)

Admin-View admin.cms.projects-index:

  • Liste aller Projekte (Titel, Status, Preis, Published, Order)
  • Erstellen/Bearbeiten Modal oder Inline
  • Felder: alle aus 2.2
  • Galerie-Management via MediaPicker
  • Bild-Upload via MediaLibraryUploader
  • Sortierung per Drag & Drop oder Order-Feld
  • Publish/Unpublish Toggle

2.6 Route für Immobilien-Show anpassen

// Vorher:
Route::get('/immobilien/{slug}', function (string $slug) {
    $project = config("content.themes.{$theme}.immobilien_projects.projects.{$slug}");
    ...
});

// Nachher:
Route::get('/immobilien/{slug}', function (string $slug) {
    $project = CmsProject::where('slug', $slug)->published()->firstOrFail();
    return view('web.immobilien-show', ['project' => $project->toFrontendArray()]);
});

Ergebnis Phase 2: Immobilien-Projekte in DB, editierbar im CMS, Frontend nutzt Model.


Phase 3 Content-Migration (config → DB)

3.1 Content-Struktur analysieren

Die config/content.php enthält das b2in-Theme mit folgenden Sektionen:

Page Section Typ
global announcement_bar Text + Links
global header Navigation
global footer Text + Links
home hero Text + Bild + Stats
home founder_bar Text + Bild
home synergie_section Text + Bild
home vision_section Text + Bild
home ecosystem_core Text + Items
home cta_section Text + Link
home brand_worlds Text + Items
about about_hero, our_story, our_values, leadership_team Diverse
immobilien immobilien_hero_v2, immobilien_warum_dubai, immobilien_kaufprozess, immobilien_bruecke, immobilien_mindset, immobilien_moebel_vorteil Diverse
faq FAQ-Kategorien Q&A
netzwerk Hero, Stats, Sections Diverse
contact Form-Info Text
impressum/privacy/terms/cookie-policy Langtext HTML

3.2 CmsContentSeeder erstellen

Strategie: Alle b2in-Inhalte aus config/content.php in flux_cms_contents überführen.

  • Key-Schema: {page}.{section}.{field} (z.B. home.hero.title, about.our_story.title)
  • Typen: text, html, image, json (für Arrays wie pillars, stats, navigation)
  • Gruppen: home, about, immobilien, netzwerk, faq, contact, impressum, privacy, terms, cookie_policy, global (Header, Footer)

Datei: database/seeders/CmsContentSeeder.php liest config/content.php und schreibt in DB.

3.3 Seeders ausführen & verifizieren

php artisan db:seed --class=CmsContentSeeder

Ergebnis Phase 3: Alle b2in-Inhalte in der DB, abrufbar über cms('home.hero.title').


Phase 4 CMS Admin-Backend

4.1 CMS als eigener Menüpunkt

Das CMS wird im Admin-Portal (portal.b2in.test) als eigener Top-Level-Menüpunkt "CMS" in der Sidebar integriert.

Sidebar-Erweiterung (resources/views/components/layouts/app/sidebar.blade.php):

CMS
├── Dashboard       (Übersicht: Anzahl Contents, Medien, Projekte)
├── Inhalte         (Content-Editor für Text/HTML/Image/JSON Keys)
├── Projekte        (Immobilien-CRUD  aus Phase 2)
├── Medienbibliothek (Upload, Grid, Conversions)

4.2 CMS-Layout

Entscheidung: Die CMS-Views nutzen das bestehende Admin-Portal-Layout (admin-master.blade.php / app.blade.php), damit Navigation und User-Menü konsistent bleiben.

→ Das Reference-Layout layout-cms.blade.php wird nicht als separates Layout genutzt, sondern als Vorlage für die Content-Struktur innerhalb des bestehenden Layouts.

4.3 Admin-Views erstellen

Aus den Package-Referenz-Views nur die benötigten kopieren und anpassen:

View Quelle Ziel
Dashboard admin-reference/cms/dashboard.blade.php livewire/admin/cms/dashboard.blade.php
Content-Editor admin-reference/cms/content-index.blade.php livewire/admin/cms/content-index.blade.php
Medienbibliothek admin-reference/cms/media-index.blade.php livewire/admin/cms/media-index.blade.php
MediaPicker admin-reference/cms/media-picker.blade.php livewire/admin/cms/media-picker.blade.php
MediaUploader admin-reference/cms/media-library-uploader.blade.php livewire/admin/cms/media-library-uploader.blade.php
Projekte Neu erstellen livewire/admin/cms/projects-index.blade.php

Nicht benötigt (vorerst): news-index, industries-index, faqs-index, linkedin-index, downloads-index, team-index, search-index

4.4 Livewire-Komponenten einrichten

mkdir -p app/Livewire/Admin/Cms/

Aus Package kopieren + Namespace anpassen:

  • MediaLibraryUploader.phpApp\Livewire\Admin\Cms
  • MediaPicker.phpApp\Livewire\Admin\Cms
  • MediaUploader.phpApp\Livewire\Admin\Cms

4.5 Admin-Routes registrieren

In routes/admin.php innerhalb der bestehenden auth-Middleware-Gruppe:

// Flux CMS Routes
Volt::route('admin/cms', 'admin.cms.dashboard')->name('cms.dashboard');
Volt::route('admin/cms/content', 'admin.cms.content-index')->name('cms.content.index');
Volt::route('admin/cms/media', 'admin.cms.media-index')->name('cms.media.index');
Volt::route('admin/cms/projects', 'admin.cms.projects-index')->name('cms.projects.index');

Ergebnis Phase 4: Funktionierendes Admin-Backend unter portal.b2in.test/admin/cms mit Dashboard, Content-Editor, Medienbibliothek und Projekte-CRUD.


Phase 5 Frontend-Umstellung (config → cms)

5.1 Strategie: Dualer Betrieb mit Fallback

Die Umstellung erfolgt inkrementell. Jede Section einzeln umstellen, mit Fallback auf config():

// Vorher (Hero.php):
$this->content = config("content.themes.{$theme}.hero", []);

// Nachher:
$this->content = $this->loadFromCms('home.hero');

// Fallback-Methode in einem Trait oder Base-Class:
protected function loadFromCms(string $group): array
{
    $cmsContent = app(CmsContentService::class)->getGroup($group);
    if (empty($cmsContent)) {
        $theme = config('app.theme', 'b2in');
        $section = Str::afterLast($group, '.');
        return config("content.themes.{$theme}.{$section}", []);
    }
    return $cmsContent;
}

5.2 Sections schrittweise umstellen

Reihenfolge (nach Priorität / Sichtbarkeit):

  1. Home-Page Sections:

    • Hero → home.hero
    • FounderBar → home.founder_bar
    • ContentSection → home.{section} (dynamisch)
    • VisionSection → home.vision_section
    • EcosystemCore → home.ecosystem_core
    • CTASection → home.cta_section
  2. Globale Elemente:

    • Header (Navigation) → global.header
    • Footer → global.footer
    • AnnouncementBar → global.announcement_bar
  3. Immobilien-Seite (statischer Content):

    • HeroV2 → immobilien.hero_v2
    • WarumDubai → immobilien.warum_dubai
    • Kaufprozess → immobilien.kaufprozess
    • Brücke → immobilien.bruecke
    • Mindset → immobilien.mindset
    • MöbelVorteil → immobilien.moebel_vorteil
    • Projekte-Liste → CmsProject::published()->ordered() (aus Phase 2)
  4. Unterseiten:

    • About
    • FAQ
    • Contact
    • Impressum / Privacy / Terms / Cookie-Policy
    • Netzwerk
    • Service / Portfolio

5.3 Immobilien-Route umstellen

// routes/web.php  von config auf Model:
Route::get('/immobilien/{slug}', function (string $slug) {
    $project = \App\Models\CmsProject::where('slug', $slug)
        ->published()
        ->firstOrFail();

    return view('web.immobilien-show', ['project' => $project->toFrontendArray()]);
})->name('immobilien.show');

Die immobilien.blade.php Projekte-Liste ebenfalls umstellen:

// Vorher: $projects = config("content.themes.{$theme}.immobilien_projects", []);
// Nachher: $projects = CmsProject::published()->ordered()->get();

5.4 Bilder umstellen

- asset('img/assets/' . $heroV2['image'])
+ cms_media_url('immobilien.hero_v2.image', 'hero')

Ergebnis Phase 5: b2in-Frontend liest Inhalte aus DB + CmsProject-Model, editierbar über Admin.


Phase 6 Medienbibliothek & Bilder

6.1 Bestehende Bilder importieren

Alle b2in-Bilder (aus public/img/assets/) in die CMS-Medienbibliothek importieren:

  • b2in/ allgemeine b2in-Bilder (Hero, Founder, Sections)
  • expose/ Immobilien-Projektbilder

6.2 CmsMediaSeeder

Seeder erstellt CmsMedia-Einträge für alle bestehenden Bilder und verknüpft sie mit den CmsContent-Keys vom Typ image.

6.3 Bildprofile definieren

In config/flux-cms.php:

  • hero → 1920×800 (Hero-Banner)
  • card → 768×512 (Kacheln, Sections)
  • thumbnail → 400×300 (Listen, Übersichten)
  • avatar → 400×400 (Team-Fotos, Founder)
  • gallery → 1200×900 (Projekt-Galerie)
  • og_image → 1200×630 (Social Sharing)

6.4 Conversions generieren

php artisan flux-cms:clear-cache

Ergebnis Phase 6: Alle Bilder in Medienbibliothek, Conversions generiert, URLs aufgelöst.


Phase 7 Tests

7.1 Referenz-Tests kopieren (selektiv)

mkdir -p tests/Feature/Cms
cp packages/flux-cms/core/tests-reference/Feature/Cms/CmsMediaTest.php tests/Feature/Cms/
cp packages/flux-cms/core/tests-reference/Feature/Cms/CmsContentServiceTest.php tests/Feature/Cms/

7.2 Projektspezifische Tests

  • CmsProjectTest CRUD, published/unpublished, toFrontendArray(), Validierung
  • CmsContentSeederTest Prüft ob alle Keys aus config in DB existieren
  • CmsAdminAccessTest Prüft Zugriffskontrolle auf CMS-Admin-Routen
  • ImmobilienRouteTest Prüft /immobilien/{slug} mit DB-Daten
  • FrontendFallbackTest Prüft dualen Betrieb (CMS → config Fallback)
  • MediaIntegrationTest Upload, Conversion, URL-Auflösung

7.3 Tests ausführen

php artisan test --compact --filter=Cms
php artisan test --compact --filter=Immobilien

Ergebnis Phase 7: Alle CMS-Funktionalitäten sind getestet.


Phase 8 Feinschliff & Dokumentation

8.1 Cache & Performance

  • CMS-Content-Cache aktivieren
  • Eager Loading optimieren
  • Prüfen: Keine N+1-Queries auf Frontseiten

8.2 config/content.php aufräumen

  • Nach vollständiger Umstellung: b2in-Theme-Daten als @deprecated markieren
  • Noch nicht entfernen (Fallback für andere Themes!)
  • Immobilien-Projekte aus Config entfernen (leben jetzt in DB)

8.3 Sidebar-Berechtigungen

  • CMS-Zugang über Spatie-Permission absichern (permission:manage-cms)
  • CMS-Menüpunkt nur für berechtigte User anzeigen

8.4 Dokumentation

  • Diesen Plan aktualisieren mit Status
  • Notizen für Integration weiterer Subseiten (b2a, stileigentum, style2own)

Offene Fragen / Entscheidungen

# Frage Entscheidung
1 Alle flux-cms Migrations laufen lassen oder nur contents + media? Empfehlung: Alle (leere Tabellen stören nicht)
2 CmsProject: Eigene Migration oder flux-cms erweitern? Eigene Migration im Projekt
3 FAQ-Daten: Vorerst in config belassen oder direkt in flux_cms_faqs? Vorerst config
4 Magazin: Eigenes System belassen oder später auf CMS? Vorerst belassen
5 Andere Themes (b2a etc.) weiterhin via config()? Ja

Fortschritt

Phase Status Notizen
1 Installation & Infrastruktur Fertig 2026-03-18: Package installiert, Config angepasst, Migrations gelaufen, Helpers eingerichtet, 434 Tests grün
2 Immobilien-Model & CRUD Fertig 2026-03-18: Migration, Model, Factory, Seeder, 9 Tests grün. CRUD Admin-View folgt in Phase 4.
3 Content-Migration Fertig 2026-03-18: 61 Sections in 8 Gruppen migriert, Section-als-JSON-Ansatz, 8 Tests grün
4 CMS Admin-Backend Fertig 2026-03-18: Dashboard, Content-Editor, Projekte-CRUD, Medienbibliothek, Sidebar-Menü, MediaPicker/Uploader, 16 Tests grün
5 Frontend-Umstellung Offen
6 Medienbibliothek Offen
7 Tests Offen
8 Feinschliff Offen