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

495 lines
26 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
```php
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):
```php
'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:
```css
@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:
```css
[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
```bash
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
```bash
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
```bash
php artisan test --compact --filter=Businessportal24HomeTest
```
### Lint
```bash
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
```blade
<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)
```blade
<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)
```blade
<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>
```
### Dunkles Panel (Newsletter / CTA / Footer)
```blade
<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.