# Migration Guide: Google AI Builder Apps -> Local Docker Stack > **CRITICAL WARNINGS & BEST PRACTICES (READ BEFORE MIGRATION):** > > 1. **PYTHON PROMPTS (F-STRINGS STRENG VERBOTEN):** Nutze **NIEMALS** `f"""..."""` für komplexe Prompts mit JSON/Markdown. Das führt zu unlösbaren `SyntaxError: unterminated string literal` Schleifen. Nutze **AUSSCHLIESSLICH** `r"""... """.format(...)`. > 2. **SDK WAHL (MODERN FIRST):** Das alte `google-generativeai` Paket ist "Legacy". Nutze für alle neuen Projekte das moderne **`google-genai`** Paket. Es löst alle Probleme mit API-Versionen (`v1beta`) und unterstützt JSON-Modus/Schemata nativ. > 3. **DOCKER VOLUMES (404-FALLE):** Mounte **NIEMALS** das gesamte App-Verzeichnis (`.:/app`), wenn darin ein `dist`-Ordner (Build-Artefakt) im Image liegt. Du löschst damit die gebaute Web-App im Container. Mounte nur die spezifische Orchestrator-Datei. > 4. **FRONTEND BUILD:** `vite`, `typescript` etc. gehören in `dependencies`, NICHT `devDependencies`, da sie sonst im Docker-Multi-Stage-Build fehlen. --- ## 0. Der "Quick-Start" Checkliste (5-Minuten-Plan) 1. **SDK:** Steht `google-genai` in der `requirements.txt`? (Wenn nein -> hinzufügen). 2. **Prompts:** Sind alle Prompts als `.format()`-Strings angelegt? (Wenn nein -> umstellen). 3. **Package.json:** Sind `vite`, `typescript`, `react-router` in `dependencies`? (Wenn nein -> verschieben). 4. **Docker-Compose:** Wird nur die `.py`-Datei gemountet? (Wenn nein -> korrigieren). 5. **Vite Config:** Ist `base: './'` gesetzt? (Muss immer). --- ## 1. Vorbereitung & Abhängigkeiten (Common Pitfalls) Bevor Code kopiert wird, m.ssen die Grundlagen stimmen. ### 1.1 Package.json Check (Frontend Build-Falle) Generierte Apps haben oft kein `express`, da sie keinen Server erwarten. Noch wichtiger ist, dass kritische Build-Tools oft fälschlicherweise in `devDependencies` deklariert werden. * **Aktion:** Öffne `package.json` der App. * **Prüfung 1 (Backend):** Steht `express` unter `dependencies`? * **Fix 1:** ```json "dependencies": { ... "express": "^4.18.2", "cors": "^2.8.5" } ``` * **Prüfung 2 (Frontend Build):** Stehen Build-Tools wie `vite`, `@vitejs/plugin-react` oder `typescript` unter `devDependencies`? * **Fix 2 (KRITISCH):** Verschiebe **alle** `devDependencies` in die `dependencies`. Der `npm install`-Befehl im `Dockerfile` installiert `devDependencies` standardmäßig nicht, was zu einem fehlgeschlagenen `npm run build` führt. ### 1.2 Datenbank-Datei Docker kann keine einzelne Datei mounten, wenn sie auf dem Host nicht existiert. * **Fehler:** "Bind mount failed: ... does not exist" * **Fix:** VOR dem ersten Start die Datei anlegen: ```bash touch mein_neues_projekt.db ``` ### 1.3 Vite Base Path (White Screen Fix) Wenn die App unter einem Unterverzeichnis (z.B. `/gtm/`) l.uft, findet sie ihre JS/CSS-Dateien nicht, wenn Vite Standard-Pfade (`/`) nutzt. * **Datei:** `vite.config.ts` * **Fix:** `base` auf `./` setzen. ```typescript export default defineConfig({ base: './', // WICHTIG f.r Sub-Pfad Deployment // ... }); ``` ### 1.4 Python Dependencies & Shared Libraries (Critical Pitfall) Das Projekt nutzt ein zentrales `helpers.py`, das von mehreren Services geteilt wird. Dies f.hrt oft zu `ModuleNotFoundError`, da eine kleine App (wie `gtm-architect`) nicht alle Bibliotheken ben.tigt, die in `helpers.py` importiert werden (z.B. `gspread`, `pandas`). * **Fehler:** `ModuleNotFoundError: No module named 'gspread'` * **Ursache:** Die `gtm-architect/requirements.txt` enth.lt `gspread` nicht, aber `helpers.py` versucht es zu importieren. * **Fix (in `helpers.py`):** Machen Sie "exotische" Importe optional. Dies ist die robusteste Methode, um die Kompatibilit.t zu wahren, ohne die `requirements.txt` kleiner Apps aufzubl.hen. ```python # Beispiel in helpers.py try: import gspread GSPREAD_AVAILABLE = True except ImportError: GSPREAD_AVAILABLE = False gspread = None # Wichtig, damit Referenzen nicht fehlschlagen ``` * **Fix (in `requirements.txt`):** Stellen Sie sicher, dass die f.r die App **unmittelbar** ben.tigten Bibliotheken vorhanden sind. F.r `gtm-architect` sind das: ```text google-generativeai google-genai Pillow requests beautifulsoup4 ``` ### 1.5 Python Syntax & F-Strings (Der Prompt-Albtraum) Multi-Line Prompts in Kombination mit `f-strings`, JSON und Markdown führen in Docker-Umgebungen zu **extrem hartnäckigen Syntaxfehlern** (`SyntaxError: unterminated string literal`), die oft nicht reproduzierbar wirken. * **Das Problem:** Der Python-Parser stolpert über verschachtelte Anführungszeichen (`"`, `'`), geschweifte Klammern `{}` (die in JSON und f-strings vorkommen) und Backslashes. Ein einziges falsch interpretiertes Zeichen sprengt den gesamten String. * **ULTIMATIVE LÖSUNG (Die einzig wahre Methode):** Vergessen Sie `f-strings` für komplexe Prompts! Nutzen Sie **Raw Strings (`r"""..."""`)** kombiniert mit der **`.format()` Methode**. 1. **Raw Strings (`r"..."`):** Verhindern, dass Backslashes als Escape-Sequenzen interpretiert werden. 2. **`.format()`:** Trennt den Text sauber von den Variablen. **FALSCH (Explosionsgefahr):** ```python prompt = f""" Analysiere "{request.name}". Antworte im JSON-Format: {{"key": "value"}} """ ``` **RICHTIG (Robust & Sicher):** ```python prompt = r""" Analysiere "{name}". Antworte im JSON-Format: {{"key": "value"}} """.format(name=request.name) ``` ### 1.6 Volume Mounts & Datei-Synchronisierung (Phantom-Fehler) Wenn Sie Code ändern, der Fehler aber bestehen bleibt ("Geisterfehler"), synchronisiert Docker die Datei nicht korrekt. * **Symptom:** `SyntaxError` an Zeilen, die Sie gerade korrigiert haben. * **Ursache:** Einzeldatei-Mounts (`- ./file.py:/app/file.py`) sind oft unzuverlässig, besonders wenn die Inode der Datei durch Editoren geändert wird. * **Lösung:** Mounten Sie das **gesamte Verzeichnis** (`- ./my-app:/app`) oder bauen Sie das Image neu (`COPY . .` im Dockerfile) und entfernen Sie den Volume-Mount temporär zur Diagnose. --- ## 2. Die Backend-Bridge (`server.cjs`) Dies ist der Node.js Server im Container. Er muss **robust** gegen Timeouts sein und Pfade dynamisch erkennen (Dev vs. Prod). --- ## 3. Docker Optimierung (Multi-Stage) Wir nutzen **Multi-Stage Builds**, um das Image klein zu halten (kein `src`, keine Dev-Tools im Final Image). --- ## 4. Docker Compose & Mounts (WICHTIGER PITFALL) **WARNUNG: Lokale Dateien .berschreiben den Container-Code!** --- ## 5. Nginx Proxy Achtung beim Routing. Wenn die App unter `/app/` laufen soll, muss der Trailing Slash (`/`) stimmen. --- ## 6. Frontend Anpassungen (React) 1. **API Calls:** Alle direkten Aufrufe an `GoogleGenAI` entfernen. Stattdessen `fetch('/api/run', ...)` nutzen. 2. **Base URL:** In `vite.config.ts` `base: './'` setzen (siehe Punkt 1.3). --- ## Appendix A: GTM Architect Fixes & Gemini Migration ### A.1 - A.4 (Siehe .ltere Versionen f.r Prompt-Fixes & GenerativeModel API) ### A.5 Image Generation 2.0 (Hybrid Approach - Jan 04) Um die Einschr.nkungen der "Text-only" Modelle und die regionale Verf.gbarkeit von Imagen 3 zu umgehen, nutzen wir einen hybriden Ansatz. **1. Anforderungen** * **Bibliothek:** `google-genai` (v1.x) MUSS installiert sein (`pip install google-genai`). `google-generativeai` (v0.x) ist veraltet. * **Bildverarbeitung:** `Pillow` muss installiert sein (`pip install Pillow`). **2. Die Logik (Text vs. Bild)** Das System entscheidet automatisch, welches Modell genutzt wird: * **Szenario A: Generisches Bild (Text-to-Image)** * **Modell:** `imagen-4.0-generate-001`. * **Szenario B: Produkt-Integration (Image-to-Image)** * **Modell:** `gemini-2.5-flash-image`. ### A.6 Gemini SDK-Chaos & Modell-Verfügbarkeit (Kritische Erkenntnis) Ein wiederkehrendes Problem bei der Migration ist der Konflikt zwischen SDK-Versionen und regionalen Modell-Beschränkungen, sowie die schnelle Evolution der API-Schnittstellen. **1. Das SDK-Dilemma** Es existieren zwei parallele Google SDKs, und selbst innerhalb von `google-generativeai` ändern sich die Modulstrukturen schnell: 1. **`google-generativeai` (Legacy):** Versionen wie `0.3.0` verhalten sich anders als neuere. Oft instabil bei neuen Modellen, wirft Deprecation-Warnungen. Import: `import google.generativeai`. 2. **`google-genai` (Modern):** Erforderlich für Imagen 4 und Gemini 2.x Features. Import: `from google import genai`. **KRITISCHES PROBLEM: `ImportError` für `Schema` und `Content` mit `google-generativeai==0.3.0`** * **Fehler:** `ImportError: cannot import name 'Schema' from 'google.generativeai.types'` oder `ImportError: cannot import name 'Content' from 'google.generativeai.types'`. * **Ursache:** In älteren Versionen des `google-generativeai`-SDK (z.B. `0.3.0`, wie in diesem Projekt verwendet) existierten diese Klassen (`Schema`, `Content`) nicht an den gleichen Importpfaden wie in neueren Versionen oder wurden gar nicht als separate Klassen verwendet. * **LÖSUNG (für `google-generativeai==0.3.0`):** * Entferne **alle** Importe für `Schema` und `Content` (z.B. `from google.generativeai.types import HarmCategory, HarmBlockThreshold`). * Ersetze **alle** Instanziierungen von `Schema(...)` durch einfache Python-Dictionaries, die direkt das JSON-Schema repräsentieren. Die `generation_config` akzeptiert in dieser Version direkt das Dictionary. **2. Der "404 Not Found" Modell-Fehler** Oft liefert die API einen 404 Fehler f.r ein Modell (z.B. `gemini-1.5-flash`), obwohl es laut Dokumentation existiert. * **Ursache:** Regionale Beschr.nkungen (EU vs US) oder Account-Berechtigungen. * **Erkenntnis:** Wenn 1.5 Flash nicht geht, funktioniert oft **`gemini-2.0-flash`** problemlos. * **Best Practice:** Implementiere eine **Kandidaten-Liste** (Fallback-Loop) f.r Modelle. **3. SDK Syntax-Fallen** Das neue SDK (`google-genai`) hat ge.nderte Methodennamen: * Statt `generate_image` (Singular) wird oft **`generate_images`** (Plural) erwartet. * Modelle f.r Bildgenerierung (Imagen) reagieren allergisch auf `response_mime_type="application/json"`. Dieses Feld MUSS bei Imagen-Modellen weggelassen werden. **Gold-Standard f.r Modell-Wahl (Python):** ```python candidates = ['imagen-4.0-generate-001', 'imagen-3.0-generate-001'] for model in candidates: try: # Versuch des API-Calls break except ClientError as e: if "404" in str(e): continue raise e ``` --- ## 7. Troubleshooting & Lessons Learned (Jan 2026) ### 7.5 Double JSON Encoding (Database Trap) * **Problem:** Wenn `json.dumps()` sowohl im Backend beim Speichern als auch in der DB-Klasse aufgerufen wird, landet "Stringified JSON" in der DB. Beim Laden im Frontend crasht React, da es einen String statt eines Objekts erh.lt. * **Fix Backend:** Speichere rohe Dictionaries in der DB-Klasse. * **Fix Frontend:** Nutze eine robuste Parse-Funktion, die `JSON.parse()` mehrfach versucht: ```javascript const parseData = (d) => (typeof d === 'string' ? JSON.parse(d) : d); ```