Umsetzung der beiden finalen Webseitentexte aus dev/2026-08-28/. Die angekündigte Aufgabenliste umsetzung-03-09-2026.md war leer, Grundlage sind daher die Umsetzungshinweise in den PDFs selbst. - Neue Felder in cms_brands: sections, widget_label, cta_title, cta_text. Einleitung und Leistungskacheln reichten für diese Texte nicht aus. - Die als Vertiefung gelieferten Blöcke werden aufklappbar dargestellt, mit aria-expanded und aria-controls. Bewusst x-transition statt x-collapse, weil das Collapse-Plugin hier nicht registriert ist. - Kein zweiter CTA-Button: das schwebende Terminanfrage-Widget trägt auf der Markenseite die Beschriftung der Marke und liest den Kontext aus der Route, da es im Layout und nicht je Seite eingebunden ist. - Footer bekommt unten Platz und lange Beschriftungen brechen um, damit das Widget auf dem Smartphone nichts verdeckt. - Abschnitte sind im Admin vollständig pflegbar, inklusive Sortierung. - Interne Quellenhinweise der PDFs sind nicht übernommen; ein Test prüft, dass sie nicht im Ausgabe-HTML stehen. - BrandPageTextSeeder fasst nur die Textfelder an, Bilder, Galerie und Leistungen bleiben unangetastet. Vor der Veröffentlichung: Herstellerfreigabe einholen und die Aussage zur erhaltenen Waldfläche nur mit ausdrücklicher Bestätigung verwenden. Beides steht in der Deployment-Checkliste. 854 Tests grün (3150 Assertions), Pint sauber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Vorschau-Instanz auf dem Live-Server einrichten
Ziel: https://preview.b2in.eu zeigt den neuen Stand zur Abstimmung. Die Live-Seite bleibt
unangetastet – es wird keine einzige Datei im Live-Verzeichnis überschrieben und keine Zeile in
der Live-Datenbank geändert.
Prinzip: zweites, eigenständiges Verzeichnis · eigene .env · eigene Datenbank.
/var/www/b2in/ ← Live, bleibt wie es ist
/var/www/b2in-preview/ ← Kopie davon, darauf das Update
Pfade unten sind Beispiele. Ersetze
/var/www/b2indurch das echte Live-Verzeichnis undb2in_live/b2in_previewdurch die echten Datenbanknamen.
0. Warum nicht einfach die Live-Dateien tauschen
Zwei Gründe, die diesen Aufwand rechtfertigen:
- Der Relaunch-Seeder überschreibt CMS-Sektionen.
InteriorRelaunchCmsSeederschreibt 23 Sektionen mit den neuen Texten. Auf der Live-Datenbank ausgeführt wäre der alte Stand weg. - Migrationen sind nicht umkehrbar.
cms_brandsund die beiden Spaltensummary/highlightskommen neu dazu.
Mit einer eigenen Datenbank kann beim Testen nichts passieren, was die Live-Seite betrifft.
1. Voraussetzungen
- DNS-Eintrag
preview.b2in.eu→ dieselbe Server-IP wieb2in.eu - SSL-Zertifikat für die Subdomain (Let's Encrypt genügt)
- vhost mit
DocumentRoot /var/www/b2in-preview/public - Zweite MySQL-Datenbank plus Benutzer
- Genug Plattenplatz für eine Kopie des Live-Verzeichnisses (vor allem
storage/)
2. Sicherung ziehen
Auch wenn wir live nichts anfassen – der Dump ist zugleich die Grundlage für die Vorschau-DB.
cd /var/www/b2in
mysqldump -u USER -p b2in_live > ~/b2in_live_$(date +%F_%H%M).sql
ls -lh ~/b2in_live_*.sql # Größe prüfen, darf nicht 0 sein
3. Vorschau-Verzeichnis anlegen
Kopie des Live-Standes, inklusive vendor/. Das erspart ein composer install auf dem
Server – für livewire/flux-pro bräuchte es sonst die Zugangsdaten aus auth.json.
cp -a /var/www/b2in /var/www/b2in-preview
cd /var/www/b2in-preview
# Laufzeit-Reste der Kopie entfernen
rm -rf bootstrap/cache/*.php
rm -f public/storage # Symlink wird in Schritt 7 neu gesetzt
Zu storage/app/public (Medienbibliothek, Display-Videos): Durch cp -a liegt eine echte
Kopie in der Vorschau – sauber getrennt, kostet aber den Speicherplatz. Wenn das zu groß ist:
rm -rf storage/app/public
ln -s /var/www/b2in/storage/app/public storage/app/public
⚠️ Mit dem Symlink landen Uploads aus der Vorschau in den Live-Dateien. Zum Anschauen in Ordnung, zum Testen von Uploads nicht. Im Zweifel kopieren.
4. .env der Vorschau anpassen
Der wichtigste Schritt. Der ThemeServiceProvider sucht den aufgerufenen Host in
config/domains.php und setzt URL::forceRootUrl() samt Asset-Origin auf die dort hinterlegte
URL. Fehlt DOMAIN_B2IN_URL, greift der Vorgabewert https://b2in.test – eine Domain, die es
im Internet nicht gibt. Dann laden Bilder, Favicon und livewire.min.js nicht mehr.
cd /var/www/b2in-preview
nano .env
Diese Werte ändern:
APP_ENV=preview
APP_DEBUG=false
APP_URL=https://preview.b2in.eu
APP_DOMAIN_NAME=preview.b2in.eu
# Vorschau-Domain, damit Routing, Links und Assets stimmen
DOMAIN_B2IN=preview.b2in.eu
DOMAIN_B2IN_URL=https://preview.b2in.eu
# Assets ebenfalls auf die Vorschau-Domain, sonst laedt der Browser sie von woanders
ASSET_URL=https://preview.b2in.eu
# Eigene Datenbank
DB_DATABASE=b2in_preview
DB_USERNAME=…
DB_PASSWORD=…
# Eigener Cache-/Session-Namensraum, damit sich Live und Vorschau nicht ins Gehege kommen
CACHE_PREFIX=b2in_preview
SESSION_COOKIE=b2in_preview_session
# Keine Mails aus der Vorschau verschicken
MAIL_MAILER=log
APP_ENV=preview sorgt automatisch für noindex, nofollow in jeder Seite
(config/app.php → app.indexable). Wer ganz sichergehen will, setzt zusätzlich
SITE_INDEXABLE=false.
Nicht ändern: APP_KEY – sonst sind verschlüsselte Werte in der kopierten Datenbank
nicht mehr lesbar.
5. Datenbank der Vorschau befüllen
mysql -u USER -p -e "CREATE DATABASE b2in_preview CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u USER -p b2in_preview < ~/b2in_live_JJJJ-MM-TT_HHMM.sql
Gegenprobe, dass die Vorschau wirklich auf ihrer eigenen DB steht:
cd /var/www/b2in-preview
php artisan tinker --execute="echo config('database.connections.mysql.database');"
# muss b2in_preview ausgeben – wenn hier b2in_live steht: STOPP
6. Update einspielen
Das Archiv dev/2026-08-28/deploy/b2in-interior-update.tar.gz enthält genau die geänderten und
neuen Dateien plus die gebauten Assets (public/build/b2in, public/build/portal). Node wird
auf dem Server nicht gebraucht. Die enthaltene Dateiliste steht in deploy/dateiliste.txt.
# Archiv hochladen, dann:
cd /var/www/b2in-preview
tar xzf ~/b2in-interior-update.tar.gz
Das Archiv enthält bewusst keine .env, kein vendor/ und nichts aus storage/.
7. Artisan-Schritte
cd /var/www/b2in-preview
php artisan config:clear
php artisan storage:link
php artisan migrate --force # legt cms_brands an, ergänzt summary/highlights
# Kernmarken anlegen – überschreibt nichts, was schon gepflegt ist
php artisan db:seed --class=CmsBrandSeeder --force
# Die neuen Texte ins CMS: genau die 23 umgetexteten Sektionen
php artisan db:seed --class=InteriorRelaunchCmsSeeder --force
# Magazin: die zwei neuen Beiträge plus Reihenfolge
php artisan db:seed --class=CmsArticleSeeder --force
# Markenseiten Rotpunkt und Febrü (Zulieferung 31.08.) – nur Textfelder, Bilder bleiben
php artisan db:seed --class=BrandPageTextSeeder --force
# Display-Branding auf das Interior-Logo
php artisan db:seed --class=DisplayInteriorBrandingSeeder --force
# Medien-URLs host-unabhängig (sonst zeigen vier Playlists auf b2in.test)
php artisan db:seed --class=DisplayMediaUrlNormalizerSeeder --force
php artisan config:cache
php artisan route:cache
php artisan view:clear
Optional, nur für die Abstimmung: Beispielbilder in die Markengalerien, damit Galerie, Referenzen-Seite und Lightbox nicht leer sind. Alle Bildunterschriften beginnen mit „BEISPIEL".
php artisan db:seed --class=DemoBrandGallerySeeder --force
Wieder entfernen:
php artisan tinker --execute="App\Models\CmsBrand::query()->update(['gallery' => null]);"
8. Vorschau abschirmen
Suchmaschinen – noindex kommt schon aus APP_ENV=preview, die robots.txt gehört
zusätzlich umgestellt:
printf 'User-agent: *\nDisallow: /\n' > /var/www/b2in-preview/public/robots.txt
Passwortschutz (empfohlen, damit die Vorschau nicht zufällig gefunden wird):
htpasswd -c /etc/apache2/.htpasswd-preview vorschau
Apache:
<Directory /var/www/b2in-preview/public>
AuthType Basic
AuthName "B2in Vorschau"
AuthUserFile /etc/apache2/.htpasswd-preview
Require valid-user
</Directory>
Nginx:
auth_basic "B2in Vorschau";
auth_basic_user_file /etc/nginx/.htpasswd-preview;
9. Prüfen
| Seite | Erwartung |
|---|---|
/ |
Hero → Marken-Teaser → Vision → Sponsoring → Showroom-Display → Immobilien → CTA |
/marken |
Grauer Seitenkopf mit Bild, drei gerahmte Markenblöcke |
/marken/cabinet |
Detailseite, Galerie mit den zwei Rubriken (falls Demo-Seeder lief) |
/marken/rotpunkt |
Neun Abschnitte, vier davon mit aufklappbarer Vertiefung; Button unten rechts heißt „Persönliche Küchenberatung vereinbaren" |
/marken/februe |
Elf Abschnitte, Zitat von Marcel; Button heißt „Persönliche Arbeitsplatzberatung vereinbaren" |
/referenzen |
Realisierte Projekte, darunter das Showroom-Display im Hochformat |
/magazin |
Die zwei Interior-Beiträge stehen oben |
/faq |
Rubriken „Für Ihr Zuhause" und „Für Projekte und Objekte" |
/about |
Werte: Beratung statt Verkauf, Maßarbeit, … |
/contact |
Betreffliste beginnt mit Beratungstermin |
/immobilien |
unverändert |
Und diese vier Punkte:
- Terminanfrage-Widget unten rechts öffnet sich, Absenden zeigt die Bestätigung
- Alle Links bleiben auf
preview.b2in.eu– springt einer aufb2in.eu, stimmt Schritt 4 nicht - Seitenquelltext enthält
<meta name="robots" content="noindex, nofollow"> - Die Live-Seite
https://b2in.eusieht unverändert aus
10. Aufräumen
Vorschau wieder abbauen:
rm -rf /var/www/b2in-preview
mysql -u USER -p -e "DROP DATABASE b2in_preview;"
# vhost und DNS-Eintrag entfernen
Beim späteren echten Livegang gilt Abschnitt 8 des Entwicklungsplans, nicht dieses Dokument. Vorher offen: Rechtstexte, OG-Bild, Seeder-Passwort rotieren.
Wenn etwas nicht stimmt
| Symptom | Ursache |
|---|---|
„Kein Server mit dem angegebenen Hostnamen gefunden" für Bilder, Favicon, livewire.min.js |
DOMAIN_B2IN_URL fehlt oder ist falsch geschrieben → Vorgabewert https://b2in.test. Siehe Diagnose unten. |
Links springen auf b2in.eu |
DOMAIN_B2IN / DOMAIN_B2IN_URL in Schritt 4 nicht gesetzt, oder config:cache fehlt |
| Seite ohne Styles | public/build/b2in fehlt – Archiv nicht vollständig entpackt |
| „Vite manifest not found" | dasselbe, oder build/portal fehlt für das Admin-Panel |
| Bilder fehlen | php artisan storage:link vergessen, oder storage/app/public nicht mitkopiert |
| Display-Kachel bleibt leer | Kein aktives Display mit veröffentlichter Playlist – dann wird die Sektion bewusst gar nicht angezeigt |
| Änderungen wirken nicht | php artisan config:clear && php artisan config:cache |
Diagnose: Assets zeigen auf den falschen Host
cd /var/www/b2in-preview
# 1. Was steht in der .env?
grep -E '^(APP_ENV|APP_URL|APP_DOMAIN_NAME|ASSET_URL|DOMAIN_B2IN|DOMAIN_B2IN_URL)=' .env
# 2. Was macht die Anwendung daraus? (zeigt den zwischengespeicherten Stand)
php artisan tinker --execute="echo config('domains.domains.b2in.domain_name').' -> '.config('domains.domains.b2in.url').PHP_EOL;"
# 3. Liegt ein alter Config-Cache herum?
ls -l bootstrap/cache/config.php 2>/dev/null
Steht in Zeile 2 etwas mit .test, fehlen die beiden DOMAIN_B2IN*-Zeilen. Beheben:
cd /var/www/b2in-preview
php artisan config:clear # zuerst den Cache weg, sonst wirkt die .env nicht
nano .env # DOMAIN_B2IN, DOMAIN_B2IN_URL, ASSET_URL, APP_URL setzen
php artisan config:cache
php artisan view:clear
Sicherheitsnetz seit dieser Runde: Findet der ThemeServiceProvider den aufgerufenen Host
nicht in der Konfiguration, verwendet er außerhalb von APP_ENV=production den tatsächlich
aufgerufenen Origin – die Vorschau verlinkt sich dann auf sich selbst statt auf eine fremde
Domain. In production bleibt es bei der konfigurierten URL, damit ein gefälschter Host-Header
keine Links auf fremde Domains erzeugen kann. Die .env sollte trotzdem stimmen.