presseportale/dev/frontend/ENTWICKLUNGSKONZEPT-BusinessPortal24-Frontend.md
Kevin Adametz 5b8bdf4182
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
12-05-2026 Frontend dev
2026-05-12 18:32:33 +02:00

26 KiB
Raw Blame History

Entwicklungskonzept BusinessPortal24 & Presseecho Frontend

Stand: 12. Mai 2026 Domains: businessportal24.test / businessportal24.com · presseecho.test / presseecho.com Theme-Slugs: businessportal24 (warm-rotes Editorial) · presseecho (grünes Editorial) Assets-Dir (geteilt): public/build/web/ Ziel: Editoriales DACH-Pressemitteilungs-Portal mit 1:1-Mockup-Umsetzung. Presseecho nutzt die gleiche Komponenten-Architektur wie BP24 und unterscheidet sich nur via Theme-Tokens + Brand-Konfiguration.

Dieses Dokument beschreibt den aktuellen Stand und die wichtigsten Architektur­entscheidungen der BusinessPortal24- und Presseecho-Frontend-Entwicklung. Es ist die zentrale Anlaufstelle für alle, die im Frontend weiterarbeiten oder neue Seiten ergänzen.


1. Zielbild & Designreferenzen

Das Portal folgt einer editorial-zeitungs-orientierten Ästhetik mit ruhiger Beige-Surface, klarer Hierarchie über Typografie statt Cards und einer einzigen warm-roten Akzentfarbe.

Datei Zweck
dev/frontend/Pass B _ _ Deutschland _aktiv.png Visuelle Referenz Desktop
dev/frontend/Pass B _ _ Deutschland _aktiv.html Roh-HTML-Export aus Figma (für strukturelle Analyse)
dev/frontend/Mobile _ Startseite.png Visuelle Referenz Mobile
dev/frontend/tailwind_v3/Startseite Tailwind.html Master-Vorlage der Implementierung (Tailwind v3 Export sauberer, ohne Embedded-Bilder)
dev/frontend/tailwind_v3/Branchenseite Tailwind.html Vorlage Branchenseite (offen)
dev/frontend/tailwind_v3/Detailseite Tailwind.html Vorlage Detailseite Pressemitteilung (offen)
dev/frontend/tailwind_v3/Veröffentlichen Tailwind.html Vorlage Veröffentlichen-Landing (offen)
dev/frontend/Branchenseite _ Energie _ Klima _aktiv.png / .html Hochauflösende Branchen-Vorlage
dev/frontend/Detailseite _ Pressemitteilung _aktiv.png / .html Hochauflösende Detailseite-Vorlage
dev/frontend/Ver_ffentlichen _ Variante A _aktiv_.png / .html Veröffentlichen-Vorlage
dev/frontend/Umsetzungskonzept - Frontend BusinessPortal24 Startseite.md Historisches Detailkonzept zur Startseite

Verbindlich: Die tailwind_v3-Exports sind die normative Referenz sie enthalten alle Spacings, Schriftgrößen, Tracking-Werte und Farbtöne in Klartext. Das .png dient als visuelle Bestätigung.


2. Tech-Stack

  • Framework: Laravel 12 (PHP 8.4)
  • UI: Livewire 4 + Volt 1 (single-file components)
  • CSS: Tailwind CSS v4 mit @theme-Tokens und scoped Layer-Komponenten
  • Build: Vite 6 (dualer Setup: vite.web.config.js Port 5178 / vite.portal.config.js Port 5177)
  • Interaktivität: Alpine.js v3 (initialisiert in resources/js/app.js)
  • Icons: Inline-SVG (Bunny-Fonts-Icons werden bewusst NICHT genutzt, um Render-konsistent zu bleiben)
  • Fonts (Bunny.net): Inter Tight (Sans), Source Serif 4 (Serif), JetBrains Mono (Mono)
  • Tests: Pest 3 + PHPUnit 11
  • Lint/Format: Laravel Pint (vendor/bin/pint --dirty --format agent)

3. Domain-Routing

Das Portal nutzt das bestehende ThemeServiceProvider-System aus CLAUDE.md. Beide Domains teilen sich build/web/-Assets und unterscheiden sich nur in der geladenen Theme-CSS-Datei:

Request (Host: businessportal24.test)
  → ThemeServiceProvider erkennt Domain
  → /config/domains.php liefert assets_dir = "build/web", theme = "businessportal24"
  → routes/web.php · "/" gibt businessportal24.blade.php zurück, vor­geladen mit Daten aus $webHomeData(Portal::Businessportal24)
  → resources/views/web/layouts/web-master.blade.php lädt theme-businessportal24.css + app.js

Request (Host: presseecho.test)
  → /config/domains.php liefert theme = "presseecho"
  → routes/web.php · "/" gibt presseecho.blade.php zurück, vor­geladen mit Daten aus $webHomeData(Portal::Presseecho)
  → web-master.blade.php lädt theme-presseecho.css + app.js

Lokale Domain-Simulation:

  • .env: DEV_SIMULATE_DOMAIN=true, DEV_SIMULATED_DOMAIN=businessportal24.test|presseecho.test
  • Alternativ: ?theme=businessportal24|presseecho als Query-Parameter

3.1 Generischer Daten-Provider

Der Daten-Provider $webHomeData(Portal $primaryPortal) in routes/web.php ist portal-agnostisch und liefert für beide Domains die gleichen Variablen (leadRelease, sideReleases, mostReadReleases, activeNewsrooms, industryIndex, homeStats). Aufruf:

view('web.presseecho', $webHomeData(Portal::Presseecho));
view('web.businessportal24', $webHomeData(Portal::Businessportal24));

Die Trennung der Portale geschieht über whereIn('portal', [$primaryPortal->value, Portal::Both->value]).

3.2 Brand-Konfiguration

In config/domains.php liegt pro Domain ein brand-Block, der Komponenten dynamisch befüllt (Logo-Text, Tagline, Newsletter-Topics, Footer-Legal, Meta-Texte):

'presseecho' => [
    'theme' => 'presseecho',
    'brand' => [
        'name' => 'presseecho',
        'accent' => null,                       // kein Brand-Akzent (z.B. "24")
        'tagline_short' => 'Pressemitteilungen · DACH',
        'tagline_long' => 'Fachmeldungen aus Wirtschaft und Industrie ...',
        'footer_legal' => '© :year presseecho.com · Alle Rechte vorbehalten',
        'about_label' => 'Über presseecho',
        'meta_title' => '...  presseecho',
        'meta_description' => '...',
        'newsletter_topics' => [ ... ],
    ],
],
'businessportal24' => [
    'theme' => 'businessportal24',
    'brand' => [
        'name' => 'businessportal',
        'accent' => '24',                        // markenrechtlicher Brand-Akzent
        ...
    ],
],

Komponenten (site-header, site-footer, newsletter-strip) lesen ihre Defaults aus config('domains.domains.'.config('app.theme').'.brand', [...]). Übergaben via :brand="..." überschreiben sie jederzeit.


4. Theme-System (Tailwind v4)

Datei: resources/css/web/theme-businessportal24.css

Alle Designtokens liegen in einem @theme-Block:

@theme {
    /* Surfaces */
    --color-bg: #f6f4ef;
    --color-bg-elev: #fbfaf6;
    --color-bg-rule: #e5e0d5;
    --color-bg-rule-strong: #1c1a17;
    --color-bg-card-warm: #f1ece2;       /* Warm-beige Anzeigen-Karten */
    --color-bg-card-warm-border: #d9cdb6;
    --color-topbar: #1a1f26;
    --color-topbar2: #232a33;

    /* Ink (Text-Hierarchie) */
    --color-ink: #1c1a17;
    --color-ink-2: #3d3935;
    --color-ink-3: #6e6862;
    --color-ink-4: #9a958d;
    --color-ink-on-dark: #f6f4ef;
    --color-ink-on-dark-2: #b8b3aa;

    /* Brand */
    --color-brand: #c84a1e;
    --color-brand-deep: #a23814;
    --color-brand-soft: #f4e5dd;
    --color-live: #e03a1a;
    --color-gain: #2e8540;
    --color-loss: #c8341e;
    --color-ok: #2e8540;

    /* Editorial-Akzente (auf dunklem Grund / in Card-Warm) */
    --color-accent-warm: #ff8b6f;          /* Eyebrows auf TopBar/Hero/Newsletter */
    --color-ink-on-dark-muted: #8a847b;    /* gedämpfter Text auf Dunkel */
    --color-ink-on-dark-rule: #2a2723;     /* feiner Trenner auf Dunkel */
    --color-bg-card-warm-hover: #ece5d5;
    --color-bg-card-warm-rule: #c8bda8;    /* Hairline „Anzeige" innerhalb Card-Warm */
    --color-card-warm-cat: #6e6862;
    --color-card-warm-title: #3a332b;
    --color-feature-line: #a8c8a8;         /* Decor-Linien im Feature-Bild-Fallback */
    --color-feature-dot: #c4dcc4;

    /* Typo & Layout */
    --font-sans:  "Inter Tight", "Söhne", Inter, system-ui, sans-serif;
    --font-serif: "Source Serif 4", "Source Serif Pro", Charter, Georgia, serif;
    --font-mono:  "JetBrains Mono", "SF Mono", ui-monospace, monospace;
    --container-layout: 1280px;
}

Daraus stehen Klassen wie bg-bg, text-ink-3, border-bg-rule, text-brand, text-accent-warm, bg-card-warm-hover, max-w-layout, font-serif automatisch zur Verfügung.

Wichtig: Komponenten dürfen keine Hex-Werte mehr enthalten. Stattdessen die Tokens nutzen (text-accent-warm, border-ink-on-dark-rule, text-card-warm-cat, …). So bleibt der Theme-Wechsel zwischen BP24 und Presseecho ein reiner CSS-Switch.

Wiederkehrende Komponenten-Klassen (in @layer components)

Klasse Verwendung
.eyebrow / .eyebrow.muted / .eyebrow.on-dark 11px-Vor-Label uppercase (Brand-Farbe / Grau / accent-warm für Dunkel-Sektionen)
.bp-cat Kategoriekürzel 11px uppercase brand
.bp-tag Solid-Brand-Tag (z. B. „TOP-MELDUNG", „Top-Meldung")
.rule-strong 1 px-Hairline auf --color-bg-rule-strong
.rule 1 px-Hairline auf --color-bg-rule
.bg-topbar-grad 135°-Gradient TopBar → Topbar2 (TopBar, CTA, Footer, Newsletter)
.bg-feature-grad 135°-Gradient (Featured-Top-Bild-Fallback)
.bg-hero-grad 135°-Gradient (Hero-Bild-Fallback)
.ticker-marquee-track Endlos-Laufband (CSS-Keyframe bp-ticker-marquee, Dauer per --bp-ticker-duration, default 42 s; respektiert prefers-reduced-motion)

Utility-Klassen (in @layer utilities)

  • .pulse-dot 1.6 s ease-in-out Animation (Live-Ticker, „heute aktiv"-Badge)
  • .tabular-nums font-variant-numeric: tabular-nums

Plus eine globale Regel:

[x-cloak] { display: none !important; }   /* Alpine.js Init-Schutz */

5. Komponenten-Architektur

5.1 Layout

resources/views/web/layouts/web-master.blade.php
└── @yield('content')

Das Layout lädt das theme-spezifische CSS via @vite. Domain-spezifische Fonts werden nur für businessportal24 von bunny.net gezogen.

5.2 Startseite

resources/views/web/businessportal24.blade.php
├── <x-web.site-header />                ← TopBar + Header + Nav + Live-Ticker
├── <main>
│   ├── <x-web.focus-hero />              ← „Im Fokus" Hero + Sidebar „Was sonst zählt"
│   ├── <section> 1.7fr/1fr Grid
│   │   ├── <livewire:web.press-release-feed />
│   │   └── <aside>
│   │       ├── <x-web.most-read />
│   │       ├── <x-web.publisher-cta />
│   │       └── <x-web.active-newsrooms />
│   ├── <x-web.industry-spotlight />
│   ├── <x-web.events-week />
│   ├── <x-web.industry-index />
│   ├── <x-web.newsletter-strip />
│   └── <x-web.quality-summary />
└── <x-web.site-footer />

5.3 Komponenten-Übersicht

Datei Rolle Datenquelle
site-header.blade.php Top-Utility-Bar (Datum + Ausgabe-Tabs + Sprache/Links), Brand-Header (Logo + Suche + Anmelden + Veröffentlichen), Unter-Nav. Inkl. Such-Overlay + Burger-Mobile-Nav via Alpine. Statisch (Props)
live-ticker.blade.php Dunkler AD-HOC-Streifen mit Ticker-Items + DAX-Sparkline. Mock (Props ticker, marketIndex)
focus-hero.blade.php Hauptmeldung (500 px Hero) + 4 Sidebar-Items „Was sonst zählt" + Anzeige. echtes leadRelease, sideReleases → fallback Mockup
focus-side-item.blade.php Einzelnes Sidebar-Item (Nummerierung 01-04, 64×64-Bild, Verifiziert-Icon). release ODER mock
focus-ad.blade.php Warm-beige Anzeigen-Karte mit Anzeige- + Ende-Anzeige-Hairlines. Statisch / Props
press-release-feed.blade.php (Volt) Featured-Top + Liste + In-Feed-Anzeige + „Weitere Meldungen"-Button. Tabs: Alle / Heute / Diese Woche. Pagination via WithPagination. Empty-State liefert Mock-Top + Mock-Liste + Anzeige. PressRelease mit withCount-Eager-Loading
feed-top-item.blade.php Featured-Eintrag mit 240×160-Bild. release ODER mock
feed-item.blade.php Zeilen-Eintrag 60 px Zeit / 100 px Kat. / 1fr Titel. Optional „Empfehlung"-Badge. release ODER mock
feed-ad.blade.php Inline-Anzeige mit Anzeige- + Ende-Anzeige-Hairlines. Statisch / Props
most-read.blade.php Top 4 nach Hits mit horizontalem Brand-Balkenindikator. releases → fallback Mockup
publisher-cta.blade.php Dunkle Call-to-Action mit Brand-Button + Sekundärlink. Statisch (Props submitHref, pricingHref)
active-newsrooms.blade.php Newsroom-Liste mit Marken-Initial-Quadrat + Pulse-Badge „heute aktiv". companies → fallback Mockup
industry-spotlight.blade.php „Heute im Fokus · Energie & Klima" 3-Spalten-Stat-Grid + 3 Meldungen + warme Studien-Karte mit Brand-Topborder. Aktuell Mockup
events-week.blade.php 7-Spalten-Grid „Termine & Events" mit „Heute"-Highlight und Pulse-Dot. Aktuell Mockup
industry-index.blade.php „Branchen-Index" 4×2 Grid mit Gain/Loss-Delta + Balkenindikator. industries (Category-Counts) → fallback Mockup
newsletter-strip.blade.php Dunkles Newsletter-Panel mit Email-Form + Topic-Checkboxen (links Topic-Auswahl). Aktuell Mockup
quality-summary.blade.php Warm-beige Card mit Schild-Icon zum Content-Score. Statisch
site-footer.blade.php 4-Spalten-Footer + Bottom-Bar (AGB / Cookie / DSGVO). Statisch

Alle Komponenten haben konsistente Konventionen:

  • cursor-pointer + hover:-Variante + transition-colors auf jedem klickbaren Element
  • Bei Bild-Containern: group + group-hover:scale-105 (subtiler Zoom)
  • Bei Listenelementen: group + group-hover:text-brand für den Titel
  • Alle Mockup-Inhalte sind als spätere Datenquellen markiert (Inline-Kommentare oder via Issue-Tracker)

6. Backend-Anbindung der Startseite

Datei: routes/web.php → Closure $businessportalHomeData

Liefert dem Blade-View folgende Variablen:

Variable Quelle Verwendung
$leadRelease Neueste veröffentlichte BP24-PM focus-hero Hero
$sideReleases Nächste 4 veröffentlichte PMs (ohne Lead) focus-hero Sidebar
$mostReadReleases Top 4 nach hits most-read
$activeNewsrooms Companies mit Press-Releases letzte 7 Tage, sortiert nach heute-aktiv active-newsrooms (Mapped Array, kein Model)
$industryIndex Top-Level-Categories mit Recent/Previous-Count + Delta industry-index (Mapped Array)
$homeStats publishedCount, publishedToday, archiveSince quality-summary

SQLite-Kompatibilität: Die whereHas-Bedingung für activeNewsrooms wurde bewusst ohne HAVING geschrieben, weil SQLite keine HAVING-Clauses ohne Aggregat unterstützt. Das ist relevant für die Test-Datenbank (DB_DATABASE=testing).


7. Responsive Strategie

Breakpoint Verhalten
< sm (< 640 px) Kompaktes Datum, mini-Edition-Tabs (DE/AT/CH/EN), Such-Icon → Overlay, „PM"-Button kurz, Logo-Untertitel ausgeblendet
sm (≥ 640 px) Voller Logo-Untertitel, vollständige Buttons („Anmelden", „Veröffentlichen")
md (≥ 768 px) „Ausgabe"-Label sichtbar, inline-Suchfeld statt Icon-Button
lg (≥ 1024 px) Sprache „Deutsch" + Trennlinie + Newsletter/RSS/API sichtbar, horizontale Underline-Nav statt Burger, Live-Ticker DAX-Sparkline
xl (≥ 1280 px) ⌘K-Hinweis im Suchfeld

Mobile Navigation

Bei < lg blendet sich die Underline-Nav aus und wird durch einen Burger-Trigger ersetzt, der die aktuelle Rubrik prominent anzeigt. Klick öffnet ein abgesetztes Dropdown (absolute z-40) mit allen Rubriken als vertikale Liste. Aktive Rubrik ist Brand-farben + Check-Icon. Esc-Taste, @click.outside und das ausgewählte Item schließen das Menü.

Such-Overlay

Such-Icon-Button öffnet einen modalen Layer (fixed inset-0 z-50 bg-ink/70 backdrop-blur-sm) mit großem Suchfeld, das via Alpine $watch + $refs automatisch fokussiert wird. Esc oder Klick auf Backdrop schließt.


8. Tests

Datei: tests/Feature/Web/Businessportal24HomeTest.php

Drei Test-Szenarien:

  1. renders the editorial shell Verifiziert Statik (Header, Sektionsüberschriften, Ticker, Newsletter, Quality-Summary). Stellt sicher, dass alte Marketing-Texte („führende Plattform", „maximale Reichweite", „Exklusiv-Interview") NICHT mehr erscheinen.
  2. feed only shows published businessportal content Prüft Portal-Trennung (BP24 + Both sind sichtbar, Presseecho-Only und Drafts nicht).
  3. shows most read releases in the sidebar Prüft Hits-Sortierung in der most-read-Komponente.

Datei: tests/Feature/Web/PresseechoHomeTest.php

Drei spiegelbildliche Test-Szenarien:

  1. renders the editorial shell Identische Sektions-Checks, gegen presseecho.test.
  2. feed only shows published presseecho content Portal-Trennung gespiegelt: Presseecho + Both sichtbar, BP24-Only und Drafts nicht.
  3. shows most read releases in the sidebar Hits-Sortierung.

Stand: 6 passed (48 Assertions, beide Test-Dateien zusammen). Gesamt-Suite 215/216 (der eine Fail ApiDocumentationTest ist vorbestehend wegen fehlender docs/api/v1.yml und nicht UI-bezogen).


9. Build & Workflow

Lokale Entwicklung

npm run dev:web          # Vite Dev Server für Web-Domains (Port 5178)
npm run dev:portal       # Vite Dev Server für Portal (Port 5177)
npm run dev:all          # Beide parallel

Production-Build

NODE_OPTIONS="--max-old-space-size=4096" npm run build:web

⚠️ Build-Memory: Ohne --max-old-space-size=4096 bricht Vite mit Exit-Code 137 (OOM) ab, sobald Alpine.js + die volle Tailwind-v4-Pipeline kompiliert werden.

Tests

php artisan test --compact --filter=Businessportal24HomeTest

Lint

vendor/bin/pint --dirty --format agent

10. Entwicklungs­schritte (chronologisch)

# Datum Schritt Status
1 12.05.2026 Umsetzungskonzept erstellt + offene Fragen geklärt
2 12.05.2026 Mockup Pass B _ _ Deutschland _aktiv 1:1 in Blade/Volt überführt
3 12.05.2026 Theme-CSS auf v3-Mockup-Werte migriert (vollständiges Surface/Ink/Brand-System, Gradient-Klassen, max-w-layout)
4 12.05.2026 „Ende Anzeige"-Hairline für focus-ad ergänzt, In-Feed-Anzeigen im Feed auf eine reduziert (am Ende vor „Weitere Meldungen")
5 12.05.2026 cursor-pointer + Hover-Effekte konsistent auf allen klickbaren Elementen (Tabs, Cards, Links, Buttons, Newsletter-Topics)
6 12.05.2026 Responsive Header umgebaut: Burger-Mobile-Nav, Such-Overlay (Alpine.js), kompaktere TopBar, sichtbare Anmelden/Veröffentlichen-Buttons
7 12.05.2026 Edition-Tabs (DE/AT/CH/EN) auch auf mobile sichtbar
8 12.05.2026 Empty-State des Feeds liefert Mock-Top + Mock-Liste + Anzeige (analog Hero/Sidebar)
9 12.05.2026 Live-Ticker-Animationen: Ad-Hoc-Meldungen als Endlos-Laufband (ticker-marquee-track, respektiert prefers-reduced-motion), rechte Kurszeile blättert via Alpine alle 5,2 s vertikal durch
10 12.05.2026 Editorial-Akzente aus Hex-Hardcodings auf Theme-Tokens migriert (accent-warm, ink-on-dark-muted, ink-on-dark-rule, card-warm-*, feature-*)
11 12.05.2026 Presseecho-Theme angelegt (theme-presseecho.css grüner Brand, gleiche Token-Namen) und Presseecho-Startseite auf BP24-Komponenten umgestellt (presseecho.blade.php)
12 12.05.2026 routes/web.php: Daten-Provider generalisiert zu $webHomeData(Portal) beide Domains nutzen denselben Code-Pfad
13 12.05.2026 Brand-Konfiguration in config/domains.php pro Domain (brand.name, brand.accent, brand.tagline_*, brand.newsletter_topics, brand.footer_legal, brand.about_label) site-header, site-footer, newsletter-strip lesen daraus
14 12.05.2026 press-release-feed-Volt-Component portal-agnostisch (Prop :portal); Aufruf vom View-Layer aus
15 12.05.2026 PresseechoHomeTest analog zu Businessportal24HomeTest (3 Szenarien, RefreshDatabase)
16 12.05.2026 Aktuell offen: Detailseite, Branchenseite, Veröffentlichen-Landing für beide Domains 🟡

11. Roadmap & nächste Schritte

Reihenfolge Aufgabe Vorlage Status
1 Mobile-Feinschliff Startseite gegen dev/frontend/Mobile _ Startseite.png durchgehen, alle Sektionen testen (besonders 7-Spalten-Events und 4×2 Branchen-Index Stack-Behavior) Mobile _ Startseite.html 🟡 noch nicht final geprüft
2 Detailseite Pressemitteilung umsetzen tailwind_v3/Detailseite Tailwind.html + Detailseite _ Pressemitteilung _aktiv.png 🔴 offen
3 Branchenseite Energie & Klima umsetzen (Template für alle Kategorien) tailwind_v3/Branchenseite Tailwind.html + Branchenseite _ Energie _ Klima _aktiv.png 🔴 offen
4 Veröffentlichen-Landing umsetzen (Variante A) tailwind_v3/Veröffentlichen Tailwind.html + Ver_ffentlichen _ Variante A _aktiv_.png 🔴 offen
5 Echte Datenquellen für aktuell statische Komponenten anbinden: Live-Ticker (Ad-Hoc-Meldungen), Events-Week, Newsletter-Topics, Industry-Spotlight-Studie 🔴 offen
6 Legacy-URL-Mapping für Kategorien + Pressemitteilungen festlegen + Tests siehe Umsetzungskonzept §13 🔴 offen
7 Presseecho-Ableitung als zweites Web-Theme aus stabiler BP24-Basis 🔴 offen

Reihenfolge-Begründung: Erst wenn Detailseite + Branchenseite + Veröffentlichen vorhanden sind, sind die wiederverwendbaren Bausteine klar genug abstrahiert. Eine zu frühe Abstraktion auf Basis nur der Startseite würde Re-Work erzeugen.


12. Konventionen & Do/Don't

Do

  • Mockup-Vorlage tailwind_v3/...html als Quelle der Wahrheit nutzen. Spacings, Farben, Schriftgrößen 1:1 übernehmen.
  • Eigene Tailwind-v4-Tokens (bg-bg, text-ink-3, border-bg-rule, …) statt fester Hex-Werte verwenden Ausnahme: TopBar-spezifische #2A2723, #8A847B, #FF8B6F, die ausschließlich auf dunklem Hintergrund vorkommen.
  • cursor-pointer + transition-colors auf jedem klickbaren Element (Buttons brauchen das wegen Tailwind-Preflight explizit).
  • Mockup-Fallback in Komponenten konsequent unterstützen (@if ($release) … @else … @endif oder Mock-Props), damit Empty-States nie „leer" wirken.
  • Volt für interaktive Komponenten, klassische Blade-Components für reine Darstellung.
  • Tests bei jeder Änderung pflegen mindestens 1 Assertion pro neue sichtbare Sektion in Businessportal24HomeTest.
  • Pint nach jeder PHP-Änderung ausführen.
  • Build mit NODE_OPTIONS=--max-old-space-size=4096 dokumentieren in Skripten / CI.

Don't

  • Keine FluxUI-Komponenten im Web-Bundle (nur im Portal verfügbar).
  • Keine Marketing-Phrasen wie „führende Plattform", „maximale Reichweite", „Exklusiv-Interview" das war Pass A, wir sind auf Pass B.
  • Keine HAVING-Clauses ohne Aggregat (SQLite-Test-DB bricht).
  • Keine festen Pixel-Container > 1280 px (Layout-Token).
  • Keine Inline-style="background-color:..." für Theme-Farben stattdessen @theme-Token verwenden.

13. Wiederkehrende Snippets

Sektions-Header

<section class="max-w-layout mx-auto px-8 mt-16">
    <header class="flex items-baseline justify-between mb-4 flex-wrap gap-3">
        <h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">
            Sektionstitel <span class="text-brand">· Subtitle</span>
        </h2>
        <div class="eyebrow muted">Meta-Information</div>
    </header>
    <hr class="rule-strong">

    {{-- ... --}}
</section>

Feed-Listen-Item (60 / 100 / 1fr)

<a href="#" class="grid items-baseline gap-4 py-3.5 border-b border-bg-rule cursor-pointer hover:bg-bg-elev transition-colors group"
   style="grid-template-columns: 60px 100px 1fr;">
    <span class="font-mono text-[12px] text-ink-3">14:18</span>
    <span class="bp-cat">Kategorie</span>
    <div>
        <div class="font-serif text-[15.5px] leading-[1.3] font-medium text-ink group-hover:text-brand transition-colors">
            Titel der Meldung
        </div>
        <div class="text-[11px] text-ink-3 mt-1">Unternehmen · Stadt</div>
    </div>
</a>

Anzeigen-Block (warm-beige)

<div class="-mx-4 my-2">
    <div class="flex items-center gap-2.5 px-4">
        <span class="h-px flex-1 bg-bg-card-warm-rule"></span>
        <span class="text-[9px] font-bold tracking-[0.22em] uppercase text-ink-on-dark-muted">Anzeige</span>
        <span class="h-px flex-1 bg-bg-card-warm-rule"></span>
    </div>

    <a href="#" rel="sponsored nofollow" class="block px-4 py-4 bg-bg-card-warm cursor-pointer hover:bg-bg-card-warm-hover transition-colors">
        {{-- Titel: text-card-warm-title; Kategorie/Meta: text-card-warm-cat --}}
    </a>

    <div class="flex items-center gap-2.5 px-4">
        <span class="h-px flex-1 bg-bg-card-warm-rule"></span>
        <span class="text-[9px] font-bold tracking-[0.22em] uppercase text-ink-on-dark-muted">Ende Anzeige</span>
        <span class="h-px flex-1 bg-bg-card-warm-rule"></span>
    </div>
</div>
<section class="bg-topbar-grad text-ink-on-dark p-12">
    <div class="eyebrow on-dark mb-3">Eyebrow</div>
    <h2 class="font-serif text-[30px] font-semibold text-white leading-[1.18] tracking-[-0.4px]">Headline</h2>
    {{-- ... --}}
</section>

14. Pflege dieses Dokuments

  • Wer ein neues Feature umsetzt: Eintrag in Tabelle §10 ergänzen + ggf. §5.3 (Komponenten) und §11 (Roadmap) aktualisieren.
  • Wer einen neuen Designtoken hinzufügt: §4 aktualisieren.
  • Wer eine neue Seite/Route ergänzt: §3 (Routing) erweitern.
  • Status-Indikator pflegen:
    • erledigt und in Production-tauglichem Zustand
    • 🟡 in Arbeit oder Feinschliff nötig
    • 🔴 offen, noch nicht begonnen

Die tailwind_v3-Mockups sind die normative Quelle. Bei Konflikten zwischen .png, Roh-.html und tailwind_v3/...html gewinnt immer das tailwind_v3/-Pendant.