# Design: Modul-Integration & Supabase-Anbindung **Datum:** 2026-05-12 **Projekt:** MBO-Tech-IT Website (Next.js 15) **Supabase:** Self-hosted, Docker VM unter `supabase.mbo-tech-it.de` --- ## Ausgangssituation Die Module 01 (E-Mail), 02 (Admin-Auth), 03 (Analytics), 06-Kunden-Portal und 07-KPI-Dashboard haben ihre Code-Dateien bereits im Projekt. Modul 06-Website-CMS fehlt noch vollständig. Supabase läuft im Docker-Container, aber DB-Migrationen, Storage Buckets und Auth-Konfiguration fehlen noch. Die Supabase-Keys sind bereits in `.env.local` eingetragen. --- ## Ziel Alle 6 Module vollständig einbinden: Datenbank-Tabellen anlegen, CMS-Code integrieren, öffentliche Website-Sektionen (Hero, Über uns, Galerie, Kontakt) aus der Datenbank laden, Storage Buckets und Auth konfigurieren. --- ## Architektur ``` mbo-tech-it.de (Next.js 15 App Router) │ ├── Öffentliche Seiten ← Hero, Über uns, Galerie, Kontakt aus Supabase DB ├── /admin/* ← CMS + Analytics + Statistik (HMAC-Auth) └── /kunden/* ← Kunden-Portal (Supabase Auth) supabase.mbo-tech-it.de (Docker VM) ├── 13 DB-Tabellen ├── 4 Public Storage Buckets └── Supabase Auth (Kunden-Portal) ``` --- ## Umsetzungsplan (Option A — Modul für Modul) ### Schritt 1: DB-Migrationen Alle SQL-Dateien nacheinander im Supabase SQL-Editor ausführen: | Migration | Erstellt | |---|---| | `modules/02-admin-auth/migrations/MIGRATIONS_AUDIT_LOGS.sql` | `admin_audit_logs` | | `modules/02-admin-auth/migrations/MIGRATIONS_TOKEN_BLACKLIST.sql` | `admin_session_blacklist`, `action_token_blacklist` | | `modules/03-analytics/migrations/MIGRATIONS_PAGE_VIEWS.sql` | `page_views` | | `modules/03-analytics/migrations/MIGRATIONS_PHONE_CLICKS.sql` | `phone_clicks` | | `modules/06-website-cms/migrations/MIGRATIONS_WEBSITE_CMS.sql` | 8 CMS-Tabellen | Zusätzlich manuell: - `admin_users` Tabelle (für Admin-Auth, Tabellenname abweichend von Template: `admin_users` statt `benutzer`) - `email_queue` Tabelle (Modul 01) - `anfragen` Tabelle (Modul 06-Kunden) ### Schritt 2: Supabase-Typen ergänzen (`lib/supabase.ts`) CMS-Tabellentypen hinzufügen: - `hero_content`, `hero_badges` - `ueber_uns_content`, `ueber_uns_stats` - `galerie_bilder` - `kontakt_info`, `kontakt_oeffnungszeiten`, `kontakt_social` ### Schritt 3: Modul 06-Website-CMS Code integrieren **Neue Dateien kopieren** aus `modules/06-website-cms/files/`: API-Routen: - `app/api/admin/hero/route.ts` + bild, logo, favicon, badges - `app/api/admin/hero/badges/[id]/route.ts` (Ordner umbenennen: `id/` → `[id]/`) - `app/api/admin/galerie/route.ts` + sort - `app/api/admin/ueber-uns/route.ts` + upload, stats, stats/[id] - `app/api/admin/kontakt/route.ts` + oeffnungszeiten/[id], social/[id] - `app/api/admin/passwort/route.ts` Admin-Seiten: - `app/admin/hero/page.tsx` - `app/admin/galerie/page.tsx` - `app/admin/ueber-uns/page.tsx` - `app/admin/kontakt/page.tsx` - `app/admin/passwort/page.tsx` Komponenten: - `components/GalerieAnzeige.tsx` - `components/admin/HeroVerwaltung.tsx` - `components/admin/GalerieVerwaltung.tsx` - `components/admin/UeberUnsVerwaltung.tsx` - `components/admin/KontaktVerwaltung.tsx` - `components/admin/PasswortAendern.tsx` **Hinweis:** `SUPABASE_INTERNAL_URL` muss in den CMS-API-Routen für Docker-internen Zugriff verwendet werden. ### Schritt 4: Öffentliche Seiten dynamisieren **`app/page.tsx`** wird zu einer async Server Component, die alle CMS-Daten lädt und als Props weitergibt. **Komponenten erhalten Props statt hardcodierter Werte:** | Komponente | Datenquelle | |---|---| | `components/Hero.tsx` | `hero_content` + `hero_badges` aus Supabase | | `components/About.tsx` | `ueber_uns_content` + `ueber_uns_stats` | | `components/Contact.tsx` | `kontakt_info` + `kontakt_oeffnungszeiten` + `kontakt_social` | | `components/GalerieAnzeige.tsx` | `galerie_bilder` (neue Komponente) | **Fallback-Strategie:** Jede Sektion nutzt `try/catch`. Bei DB-Fehler greift ein hardcodierter Fallback, die Seite bleibt immer aufrufbar. **`app/layout.tsx`:** `PageTracker` von Analytics einbinden. **`components/admin/AdminNav.tsx`:** Links zu `/admin/hero`, `/admin/ueber-uns`, `/admin/galerie`, `/admin/kontakt`, `/admin/passwort` ergänzen. ### Schritt 5: npm-Pakete prüfen ```bash npm install nodemailer @types/nodemailer npm install bcryptjs @types/bcryptjs # @supabase/supabase-js + @supabase/ssr bereits vorhanden ``` ### Schritt 6: Env-Variablen ergänzen ```env SUPABASE_INTERNAL_URL=http://supabase-kong:8000 # SMTP-Felder ausfüllen (SMTP_HOST, SMTP_USER, SMTP_PASS) ``` ### Schritt 7: Infrastructure (manuell im Supabase-Dashboard) **Storage Buckets anlegen (alle Public):** - `hero-bilder` - `site-assets` - `ueber-uns-bilder` - `galerie-bilder` **Auth konfigurieren:** - Site URL: `https://mbo-tech-it.de` - Redirect URL: `https://mbo-tech-it.de/auth/callback` - E-Mail-Bestätigung aktivieren **Ersten Admin-User anlegen:** ```sql INSERT INTO admin_users (email, password_hash, name) VALUES ('jonny@mbo-tech-it.de', '', 'Admin'); ``` ### Schritt 8: Queue-Worker (instrumentation.ts) ```ts import { startEmailQueueWorker } from "@/lib/email-queue"; export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") startEmailQueueWorker(); } ``` --- ## Datenbank-Schema (13 Tabellen) | Tabelle | Modul | Typ | |---|---|---| | `email_queue` | 01 | Queue | | `admin_users` | 02 | Singleton-Liste | | `admin_audit_logs` | 02 | Protokoll | | `admin_session_blacklist` | 02 | Blacklist | | `action_token_blacklist` | 02 | Blacklist | | `page_views` | 03 | Tracking | | `phone_clicks` | 03 | Tracking | | `anfragen` | 06-Kunden | CRUD | | `hero_content` | 06-CMS | Singleton | | `hero_badges` | 06-CMS | Liste | | `ueber_uns_content` | 06-CMS | Singleton | | `ueber_uns_stats` | 06-CMS | Liste | | `galerie_bilder` | 06-CMS | Liste | | `kontakt_info` | 06-CMS | Singleton | | `kontakt_oeffnungszeiten` | 06-CMS | Liste | | `kontakt_social` | 06-CMS | Liste | --- ## Wichtige Abweichungen von den Modul-Templates - **`email_queue` — andere Spaltennamen:** Das Modul-Template definiert `to_addr`, `text`, `attempts`, `max_attempts`, `last_error`. Der tatsächliche Code (`lib/email-queue.ts` + `lib/supabase.ts`) verwendet `mail_from`, `mail_to`, `reply_to`, `body_text`, `retry_count`, `error_last`. Die DB-Migration muss die Spaltennamen aus dem Code verwenden, **nicht** aus dem Template. - **`admin_users` statt `benutzer`:** Tabelle heißt `admin_users`, Spalten: `id, email, name, password_hash, aktiv, created_at`. - **KPI-Dashboard ohne `anfragen_positionen`:** `app/api/admin/statistik/route.ts` ist bereits ans Projekt angepasst und fragt nur `anfragen` ab (keine `anfragen_positionen` wie im generischen Template). - **`lib/supabase.ts` nutzt `SUPABASE_URL`** (nicht `NEXT_PUBLIC_SUPABASE_URL`) für den Service Client — korrekt so. - **CMS-API-Routen:** Sollen `SUPABASE_INTERNAL_URL` für Docker-internen Zugriff verwenden. --- ## Nicht im Scope - Docker-Compose-Konfiguration für Supabase (läuft bereits) - Modul 04 (Reservierungssystem) — nicht vorhanden; KPI-Dashboard und Kunden-Portal sind bereits ohne es angepasst - CI/CD-Pipeline