Lang-Dateien (Kontaktformular, Impressum, Datenschutz, de/en), Support-Link im Partnerportal, WhatsApp-Schreibweise und Platzhalter im Admin. ContactDetailsSeeder ersetzt die alten Werte in den gespeicherten CMS-Einträgen (beide Sprachen), Marken und Magazin; Display-Folien und Info-Tablet (CABINET-Showroom) bleiben unberührt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
14 KiB
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 (+49 521 986 20 100, zugleich Telefonnummer; E-Mail interior@b2in.eu), 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
CmsProjectmit 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 incategories. - Vorschau im Portal: Die Website erlaubt das Einbetten nur durch sich selbst und das Portal (
frame-ancestors,AllowPortalFraming). - Übersetzungen prüfen:
php artisan cms:untranslatedlistet 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 Aliasforge-b2in),NAS= Sicherung. - Ausgeliefert wird nur ein Tag
vX.Y.Z, auf dem Server mitbash 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
--migrationskommen. Rollback: dasselbe Skript mit dem vorigen Tag. public/buildist versioniert, weil der Server kein Node hat. Vor dem Tag lokalnpm run build:web && npm run build:portalausführen.- Inhaltsänderungen laufen über idempotente Seeder.
InteriorReleaseSeederfasst 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.
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.jpgfehlt. 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).