dev/entwicklung.md neu: Welten Interior/Immobilien, Seiten und Bausteine der Website, CMS im Portal, Store Displays mit Playlists, Betrieb (Git-Deploy, Monitoring), Datenbank, Tests, offene Punkte. Die Doku-Seite stellt Tabellen jetzt lesbar dar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
261 lines
14 KiB
Markdown
261 lines
14 KiB
Markdown
# B2in – Projektdokumentation
|
||
|
||
**Stand:** 09.10.2026 · **Version:** v2.0.6 · **Live:** b2in.eu (Website), portal.b2in.eu (Portal)
|
||
|
||
## Projektübersicht
|
||
|
||
B2in ist eine Laravel-Anwendung für mehrere Domains. Im Zentrum stehen zwei Teile:
|
||
|
||
- **Website b2in.eu** mit zwei Welten. Die Welt **B2in Interior** zeigt hochwertige Einrichtung von CABINET, Rotpunkt Küchen, Febrü und Otterpohl Möbelservice, dazu Showroom, Magazin und Kontakt. Die Welt **Immobilien** betrifft internationale Projekte in Dubai.
|
||
- **Portal portal.b2in.eu** mit Website-CMS, Store Displays mit Info-Tablet, Partnerverwaltung, Produkten, Regionen und Monitoring.
|
||
|
||
Im Oktober 2026 ging der Interior-Relaunch live (v2.0.0). Seitdem wird per Git-Tag ausgeliefert und der Betrieb überwacht.
|
||
|
||
Die Domains b2a, Stileigentum und Style2own bleiben erreichbar, werden aber nicht weiterentwickelt.
|
||
|
||
---
|
||
|
||
## Domains und Welten
|
||
|
||
| Domain | Zweck | Oberfläche |
|
||
|---|---|---|
|
||
| `b2in.eu` | Website B2in Interior und Immobilien-Welt | Livewire, Tailwind CSS v4, eigenes Theme `b2in` |
|
||
| `portal.b2in.eu` | Portal: CMS, Displays, Partner, Admin | Livewire, Volt, Flux UI Pro |
|
||
| `cabinet.b2in.eu` | Display-Player und Short-Links im Showroom (`public/_cabinet`) | statisches HTML/JS, holt Daten über die Display-API |
|
||
| b2a, Stileigentum, Style2own | Landingpages (geparkt) | eigene Themes |
|
||
|
||
Die Welt einer Seite ergibt sich aus `b2in_world()` in `app/helpers.php`, das Logo je Welt aus `ThemeHelper::getLogoPath()`.
|
||
|
||
| Welt | Farben | Schriften |
|
||
|---|---|---|
|
||
| Interior (Standard) | Tanne, Creme, Sand, Ocker (`#a8741f` als Akzent) | Inter, EB Garamond |
|
||
| Immobilien | Anthrazit, Dynamic Blue | Inter, IBM Plex Sans |
|
||
|
||
Lokal laufen die Domains unter `*.test` (siehe `CLAUDE.md`).
|
||
|
||
---
|
||
|
||
## Technik
|
||
|
||
| Bereich | Einsatz |
|
||
|---|---|
|
||
| Framework | Laravel 12, PHP 8.4 |
|
||
| Oberfläche | Livewire 4, Volt, Flux UI Pro 2, Alpine.js, Tailwind CSS v4 |
|
||
| Anmeldung | Laravel Fortify, Sanctum, Rollen über Spatie Laravel-Permission |
|
||
| Mehrsprachigkeit | Deutsch/Englisch: Lang-Dateien und Spatie Laravel-Translatable |
|
||
| CMS | eigenes Paket `packages/flux-cms` (Inhalte, Mediathek) und App-Module (Marken, Magazin, Referenzen) |
|
||
| Build | Vite, je Theme ein Build unter `public/build/<theme>`, Portal unter `public/build/portal` |
|
||
| Fehler und Betrieb | GlitchTip (Sentry-SDK), `/health`, Uptime Kuma, ntfy |
|
||
| Tests | Pest 3, SQLite im Arbeitsspeicher |
|
||
| Entwicklung | Dev Container: `php`, `composer`, `npm` direkt, ohne Sail |
|
||
|
||
---
|
||
|
||
## Website B2in Interior
|
||
|
||
### Seiten
|
||
|
||
| Pfad | Inhalt |
|
||
|---|---|
|
||
| `/` | Hero mit Bilder-Slideshow und Infokarte, Gründerleiste (Marcel Scheibe), Weiche Privat/Projekt, Kernmarken, „Aus der Region gefertigt“, „Gebaut auf Expertise und Vertrauen“, Vereine (Sponsoring), Live-Ansicht des Showroom-Displays, Immobilien-Teaser, Kontakt-CTA |
|
||
| `/marken` | Hero, Gründerleiste, die vier Kernmarken, Bildpause mit Zitat, Herkunft, Netzwerk, Wachstum, CTA |
|
||
| `/marken/{slug}` | Markenseite: Einleitung, Abschnitte mit aufklappbaren Vertiefungen, Leistungen, Galerie (Realisiertes Projekt / Aus der Werkstatt / Inspiration), Handwerk-Abschluss, weitere Marken |
|
||
| `/about` | Mission, Gründerleiste, Geschichte, Werte, Partner-CTA |
|
||
| `/magazin`, `/magazin/{slug}` | Magazin der Interior-Welt; alte Adressen `/magazin/1` … `/5` leiten per 301 weiter |
|
||
| `/faq` | allgemeine Fragen und Bereiche „Für Ihr Zuhause“ und „Für Projekte und Objekte“ |
|
||
| `/contact` | Kontaktformular |
|
||
| `/referenzen` | Referenzen-Modul; zurzeit ausgeblendet (Schalter im CMS) |
|
||
| `/impressum`, `/privacy`, `/terms`, `/cookie-policy` | Rechtstexte (Stand 06.10.2026: DDG, MStV, TDDDG) |
|
||
| `/embed/display/{display}` | schreibgeschützte Einbettung eines Displays (nur veröffentlichte Playlists) |
|
||
|
||
Stillgelegte Seiten leiten dauerhaft um: `/netzwerk`, `/interior`, `/partner` und `/service` auf `/marken`, `/ecosystem` auf `/partner`, `/portfolio` auf `/immobilien`.
|
||
|
||
### Bausteine
|
||
|
||
- **Hero-Slideshow:** elf Bilder, im CMS pflegbar. Je Bild Marke und Motiv in der Infokarte. Überblendung alle 7 Sekunden (einstellbar 3–30), Pause bei Hover und Fokus, Steuerung per Pfeiltasten. Eine Fortschrittslinie im Bild zeigt die verbleibende Zeit. Auf dem Handy steht die Karte unter dem Bild.
|
||
- **Gemeinsamer Hero-Stil** auf Start, Marken, Über uns und Kontakt: Goldverlauf als Rahmen, Zeile über der Überschrift, Vertrauenspunkte.
|
||
- **Termin-Widget:** WhatsApp zuerst (0521-98620100), darunter das Formular.
|
||
- **Live-Display:** Die Startseite zeigt, was im Showroom läuft, vergrößerbar und im Vollbild.
|
||
- **Sprache:** Deutsch und Englisch, Umschaltung über die Sitzung (`SetLocale`).
|
||
|
||
### Inhalte: CMS vor Lang-Datei
|
||
|
||
Jede Sektion liest zuerst das CMS (`cms_theme_section()` über `config/cms_section_map.php`). Fehlt der Eintrag, gilt die Lang-Datei `resources/lang/{de,en}/b2in.php`. Bilder kommen bevorzugt aus `public/img/assets` (WebP-Fassungen) und sonst aus der Mediathek (`theme_image_url()`, `media_url()`).
|
||
|
||
---
|
||
|
||
## Immobilien-Welt
|
||
|
||
- Seiten unter `/immobilien`: Übersicht, Projekt (`/immobilien/{slug}`), Magazin, Über B2in, FAQ, Kontakt. Eigene Navigation, eigenes Logo, blaues Farbschema.
|
||
- Projekte als `CmsProject` mit Preis in AED und Umrechnung in EUR/USD (`PriceHelper`). Die Projekte sind zurzeit nicht freigegeben und im Portal nicht verlinkt.
|
||
- Magazin der Immobilien-Welt: drei Beiträge (Escrow, Al Jaddaf, Turnkey).
|
||
|
||
---
|
||
|
||
## Magazin
|
||
|
||
Beiträge als `CmsArticle` (Titel, Untertitel und Inhalt je Sprache, Welt `interior` oder `immobilien`, Autor, Lesezeit, Veröffentlichung).
|
||
|
||
| Welt | Veröffentlicht |
|
||
|---|---|
|
||
| Interior | „Nach Maß statt von der Stange“, „Küche planen“ |
|
||
| Immobilien | Escrow, Al Jaddaf, Turnkey |
|
||
| offline | Supply-Chain, Local for Local (seit 08.10.2026) |
|
||
|
||
Absätze im Inhalt trennt eine Leerzeile. Datum und Lesezeit stehen im deutschen Format.
|
||
|
||
---
|
||
|
||
## CMS im Portal
|
||
|
||
Unter **CMS ▸ Website-Inhalte**:
|
||
|
||
| Bereich | Funktion |
|
||
|---|---|
|
||
| Übersicht | Einstieg mit Kennzahlen |
|
||
| Inhalte | **Seitenbaum** (`config/cms_pages.php`): je Seite die Sektionen mit Beschreibung. Felder je Sprache (DE/EN), Listen als Wiederholfelder, Bilder über die Mediathek. **Vorschau** der Seite daneben im Rahmen. Eine fehlende Sektion lässt sich aus der Lang-Datei anlegen. |
|
||
| Marken | die vier Kernmarken: Texte, Logo, Titelbild, Merkmale, Leistungen, Abschnitte, Galerie mit Rubriken, Fertigungsort, CTA. **Alle Textfelder je Sprache**, Bilder und Rubriken gelten für beide Sprachen. |
|
||
| Magazin | Beiträge beider Welten |
|
||
| Referenzen | Modul vorhanden, Seite und Menüpunkt zurzeit ausgeblendet |
|
||
| Medien | Mediathek mit Sammlungen (Marken, Magazin, Website), Alternativtexten je Sprache und Bildgrößen. Alle auf der Website verwendeten Bilder sind übernommen. |
|
||
|
||
Hinweise zur Pflege:
|
||
|
||
- **FAQ:** Jede Frage hat das Feld `category`. Leer heißt allgemeine Frage oben, sonst steht dort der Bereich. Überschrift und Symbol der Bereiche stehen in `categories`.
|
||
- **Vorschau im Portal:** Die Website erlaubt das Einbetten nur durch sich selbst und das Portal (`frame-ancestors`, `AllowPortalFraming`).
|
||
- **Übersetzungen prüfen:** `php artisan cms:untranslated` listet alles, was auf der englischen Seite fehlt oder noch deutsch ist.
|
||
|
||
---
|
||
|
||
## Store Displays und Info-Tablet
|
||
|
||
Unter **Cabinet ▸ Store Displays**:
|
||
|
||
| Bereich | Funktion |
|
||
|---|---|
|
||
| Übersicht | Kennzahlen, Status des Info-Tablets |
|
||
| Mediathek | Bilder und Videos der Displays (Uploads oder externe URLs) |
|
||
| Module | Inhalte nach Typ: `video-display` (Video-Playlist), `b2in` (Marken-Slides mit Interior-Logo, Bilddauer mit Nachkommastelle), `offers` (Angebote). Vorschau je Modul und je Folie. |
|
||
| Displays | physische Geräte mit **Playlists** (Entwurf und veröffentlicht), Test-Displays, Vorschau-Links mit Token |
|
||
| Info-Tablet | Öffnungszeiten (7 Tage), Tagesausnahmen mit Rücksetzung um Mitternacht, Status (offen, Hinweis, geschlossen, Warnung), Kontakt; Schnellschalter unter `/info/status` |
|
||
|
||
**API:** Die Displays fragen die API zyklisch ab, ein Neustart ist nach Änderungen nicht nötig. Medien-URLs sind relativ gespeichert und funktionieren dadurch auf jedem Host.
|
||
|
||
| Endpunkt | Zweck |
|
||
|---|---|
|
||
| `/api/display/{display}/config`, `/check` | Konfiguration und Änderungsprüfung je Gerät |
|
||
| `/api/display/overview` | Übersicht aller Geräte |
|
||
| `/api/display/preview/{token}` | Entwurf über Vorschau-Token |
|
||
| `/api/display/module/{module}/preview` | Vorschau eines Moduls |
|
||
| `/api/cabinet-tablet/status`, `/check` | Info-Tablet |
|
||
|
||
**Short-Links:** `cabinet.b2in.eu/go.php?z=CODE` mit Klickzählung in `public/_cabinet/clicks.log`. Die Datei schreibt der Player im Betrieb, deshalb ist sie nicht versioniert.
|
||
|
||
---
|
||
|
||
## Partner, Produkte, Regionen
|
||
|
||
Diese Bereiche haben eine Grundarchitektur. Seit dem Frühjahr kamen keine neuen Funktionen hinzu.
|
||
|
||
| Bereich | Funktionen |
|
||
|---|---|
|
||
| Rollen | Super-Admin, Admin, Retailer, Manufacturer, Broker, Customer |
|
||
| Partner | Einladung per Mail mit Token, Setup-Wizard, Registrierungscodes mit QR (`/reg/{role}`), Impersonation, Anonymisieren statt Löschen |
|
||
| Produkte | Produkte, Varianten, Kategorien, Marken, Kuration (`curate_products`) |
|
||
| Regionen | Hubs mit PLZ-Gebieten (Import einzeln, Bereich oder CSV) |
|
||
|
||
---
|
||
|
||
## Betrieb
|
||
|
||
Die vollständige Anleitung steht in **`dev/betrieb/README.md`**.
|
||
|
||
### Auslieferung per Git-Tag
|
||
|
||
- Remotes: `origin` = forge.adametz.media (Quelle für den Deploy, auf dem Server über den Alias `forge-b2in`), `NAS` = Sicherung.
|
||
- Ausgeliefert wird nur ein Tag `vX.Y.Z`, auf dem Server mit `bash dev/betrieb/deploy.sh vX.Y.Z [--migrations] [--seed=…]`.
|
||
- Das Skript bricht ab, bevor es etwas verändert, wenn im Verzeichnis von Hand geändert wurde, der Tag fehlt, ein Build-Manifest fehlt oder Migrationen ohne `--migrations` kommen. Rollback: dasselbe Skript mit dem vorigen Tag.
|
||
- `public/build` ist versioniert, weil der Server kein Node hat. Vor dem Tag lokal `npm run build:web && npm run build:portal` ausführen.
|
||
- Inhaltsänderungen laufen über idempotente Seeder. `InteriorReleaseSeeder` fasst alle Schritte des Relaunchs zusammen. Spätere Seeder nennt die jeweilige Tag-Notiz.
|
||
|
||
### Überwachung
|
||
|
||
| Was | Wo |
|
||
|---|---|
|
||
| Fehler in PHP und im Browser | GlitchTip `errors.adametz.media`, Projekte `server-b2in` und `browser-b2in`. Ohne Personenbezug: nur User-ID, keine Formularinhalte, E-Mails ausgeblendet. |
|
||
| Tiefer Health-Check | `/health` mit Bearer-Token (`MONITORING_HEALTH_TOKEN`): Datenbank, Cache, Queue, Scheduler-Herzschlag, Plattenplatz |
|
||
| Externer Monitor | Uptime Kuma auf `/health` und `/up`, Alarme per ntfy (Topic `b2in-ops`) und Mail |
|
||
| Geplante Aufgaben | Cron `schedule:run` jede Minute: Herzschlag, `cabinet:reset-overrides` (0 Uhr), Aufräumen alter Jobs; bei Fehlschlag ein Alarm |
|
||
| **Admin ▸ Monitoring** | Prüfungen, Version und Deploy-Zeit, geplante Aufgaben, letzte Fehler und Alarme, fehlgeschlagene Jobs, Test-Alarm |
|
||
|
||
Eine Queue braucht B2in nicht, Mails gehen sofort raus.
|
||
|
||
---
|
||
|
||
## Datenbank (Auszug)
|
||
|
||
| Bereich | Tabellen |
|
||
|---|---|
|
||
| Benutzer und Rollen | `users`, `roles`, `permissions`, `model_has_roles`, `personal_access_tokens` |
|
||
| Partner | `partners`, `partner_invitations`, `registration_codes`, `hubs`, `hub_locations` |
|
||
| Produkte | `products`, `product_variants`, `brands`, `categories`, `attributes`, `tags`, `collections` … |
|
||
| Website-CMS | `flux_cms_contents` (Sektionen je Gruppe/Schlüssel, Werte je Sprache), `flux_cms_media`, `cms_brands` (mit `field_translations`), `cms_articles` (mit `world`), `cms_projects`, `cms_references` |
|
||
| Displays | `displays`, `display_versions` (Module), `display_version_items`, `display_playlists`, `display_playlist_items`, `display_media`, `cabinet_tablet_settings` |
|
||
| Altbestand Displays | `display_videos`, `display_footer_contents` |
|
||
| System | `cache`, `jobs`, `failed_jobs`, `sessions` |
|
||
|
||
---
|
||
|
||
## Tests
|
||
|
||
1197 Tests (Pest), alle grün (Stand 09.10.2026). Sie laufen auf SQLite im Arbeitsspeicher, die MySQL-Datenbank bleibt unberührt.
|
||
|
||
```bash
|
||
php artisan test --compact # alle
|
||
php artisan test --compact tests/Feature/FooTest.php
|
||
```
|
||
|
||
Wächtertests sichern bekannte Stolpersteine ab:
|
||
|
||
- Klassenpfad und Namespace in gleicher Schreibweise, sonst Ausfall auf Linux
|
||
- Lang-Sektionen und Section-Map decken sich
|
||
- die Testsuite meldet nie an das echte GlitchTip
|
||
|
||
---
|
||
|
||
## Wichtige Dateien und Dokumente
|
||
|
||
| Datei | Inhalt |
|
||
|---|---|
|
||
| `CLAUDE.md` | Projektkontext für Entwicklung mit KI |
|
||
| `dev/betrieb/README.md` | Deploy, Livegang, Monitoring (Runbook) |
|
||
| `dev/2026-08-28/entwicklungsplan.md` | Verlauf des Interior-Relaunchs mit allen Nachträgen |
|
||
| `dev/git-deploy-monitoring/` | Baukasten Git-Deploy und Monitoring (projektübergreifend) |
|
||
| `config/cms_pages.php` | Seitenbaum und Beschreibungen im CMS |
|
||
| `config/cms_section_map.php` | Zuordnung Website-Sektion ↔ CMS-Eintrag |
|
||
| `resources/lang/{de,en}/b2in.php` | Standardtexte der Website |
|
||
| `resources/lang/{de,en}/b2in_legal.php` | Rechtstexte |
|
||
| `database/seeders/data/brand-translations-en.json` | englische Markentexte |
|
||
| `dev/DISPLAY_CMS_README.md`, `dev/DISPLAY_SETUP_LIVE.md` | Display-System |
|
||
| `DOMAINS-CONFIG.md` | Domain-Konfiguration |
|
||
|
||
Archive alter Entwürfe und stillgelegter Seiten liegen unter `dev/2026-08-28/archiv-*`, jeweils mit README.
|
||
|
||
---
|
||
|
||
## Offene Punkte
|
||
|
||
- **Datenschutzerklärung:** Der Absatz zur Fehlerprotokollierung (GlitchTip) fehlt noch. Ein Textvorschlag steht in `dev/betrieb/README.md`, Abschnitt 6.
|
||
- **OG-Bild** `img/assets/b2in-og-default.jpg` fehlt. Geteilte Links zeigen deshalb kein Vorschaubild.
|
||
- **Freigaben:**
|
||
- Herstellerfreigabe der Texte von Rotpunkt und Febrü, mit Blick auf die EmpCo-Regeln
|
||
- CABINET-Seitentext von Marcel
|
||
- Waldflächen-Aussage bei Rotpunkt
|
||
- **Englische Markentexte** einmal muttersprachlich gegenlesen lassen.
|
||
- **Logo TC Bad Salzuflen** liegt nur in geringer Auflösung vor (72 × 80 px).
|
||
- **Mailzustellung:** Im Frühjahr wurden Systemmails bei Gmail abgewiesen („sender is unauthenticated“). SPF, DKIM und DMARC der Absenderdomain prüfen.
|
||
- **Display-Feed:** Festlegen, welches Display auf der Website läuft (`referenzen.display_feed.display_id`). Ohne Eintrag läuft das erste aktive Display mit veröffentlichter Playlist.
|
||
|
||
---
|
||
|
||
*Diese Dokumentation wird mit jedem Release aktualisiert. Letzte Aktualisierung: 09.10.2026 (v2.0.6).*
|