diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..19c3ef13 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3.8' + +services: + backend: + build: + context: . + dockerfile: Dockerfile + container_name: market-intel-backend + restart: unless-stopped + volumes: + # Persist Logs + - ./Log:/app/Log + # API Keys & Config (Bind Mounts for easy editing) + - ./gemini_api_key.txt:/app/gemini_api_key.txt + - ./serpapikey.txt:/app/serpapikey.txt + - ./config.py:/app/config.py + # Optional: Mount Python script for hot-reloading logic changes + - ./market_intel_orchestrator.py:/app/market_intel_orchestrator.py + environment: + - PYTHONUNBUFFERED=1 + # Backend port is internal-only, accessed by frontend via Docker network + expose: + - "3001" + + frontend: + build: + context: ./general-market-intelligence + dockerfile: Dockerfile + container_name: market-intel-frontend + restart: unless-stopped + ports: + # Expose Frontend to Host (Synology) + # Access via http://:8085 + - "8085:80" + depends_on: + - backend + +# Optional: Define a specific network if needed, otherwise 'default' is fine. diff --git a/general-market-intelligence/Dockerfile b/general-market-intelligence/Dockerfile new file mode 100644 index 00000000..3cf2110a --- /dev/null +++ b/general-market-intelligence/Dockerfile @@ -0,0 +1,27 @@ +# Stage 1: Build the React App +FROM node:18-alpine as build + +WORKDIR /app + +# Copy package files first for better caching +COPY package.json package-lock.json ./ +RUN npm install + +# Copy source code +COPY . . + +# Build for production +RUN npm run build + +# Stage 2: Serve with Nginx +FROM nginx:alpine + +# Copy built assets from Stage 1 +COPY --from=build /app/dist /usr/share/nginx/html + +# Copy custom Nginx config +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/general-market-intelligence/nginx.conf b/general-market-intelligence/nginx.conf new file mode 100644 index 00000000..a3db8967 --- /dev/null +++ b/general-market-intelligence/nginx.conf @@ -0,0 +1,22 @@ +server { + listen 80; + + # 1. Serve React Frontend (Static Files) + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; # Support for React Router (SPA) + } + + # 2. Proxy API Requests to Backend Container + location /api/ { + # 'backend' is the service name in docker-compose.yml + # Port 3001 is where the Node.js bridge listens + proxy_pass http://backend:3001/api/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/general-market-intelligence/services/geminiService.ts b/general-market-intelligence/services/geminiService.ts index 5314b22d..0b5b3662 100644 --- a/general-market-intelligence/services/geminiService.ts +++ b/general-market-intelligence/services/geminiService.ts @@ -3,8 +3,12 @@ import { LeadStatus, AnalysisResult, Competitor, Language, Tier, EmailDraft, Sea // const apiKey = process.env.API_KEY; // Nicht mehr direkt im Frontend verwendet // const ai = new GoogleGenAI({ apiKey: apiKey || '' }); // Nicht mehr direkt im Frontend verwendet -// URL unserer lokalen Node.js API-Brücke -const API_BASE_URL = `http://${window.location.hostname}:3001/api`; +// URL Konfiguration: +// Im Production-Build (Docker/Nginx) nutzen wir den relativen Pfad '/api', da Nginx als Reverse Proxy fungiert. +// Im Development-Modus (lokal) greifen wir direkt auf den Port 3001 zu. +const API_BASE_URL = import.meta.env.PROD + ? '/api' + : `http://${window.location.hostname}:3001/api`; // Helper to extract JSON (kann ggf. entfernt werden, wenn das Backend immer sauberes JSON liefert) const extractJson = (text: string): any => { diff --git a/readme.md b/readme.md index 58820d43..0d70a0d1 100644 --- a/readme.md +++ b/readme.md @@ -707,3 +707,43 @@ Der Prozess für den Benutzer bleibt weitgehend gleich, ist aber technisch solid **Schritt 4 & 5: Reporting & Personalisierte Ansprache** - **Ergebnis-Darstellung:** Die faktenbasierten Analyseergebnisse werden im Frontend angezeigt. - **Kampagnen-Generierung:** Die KI nutzt die validierten "Digitalen Signale" als Aufhänger, um hyper-personalisierte und extrem treffsichere E-Mail-Entwürfe zu erstellen. Dabei werden **operative Schmerzpunkte ("Grit")** und **Social Proof** (Referenzkunden) aggressiv genutzt, um Insider-Status zu demonstrieren. + +## 10. Deployment & Online-Zugriff (Production) + +Für den dauerhaften Betrieb ("Production Mode") auf einem Server (z.B. Synology Diskstation) wird die Anwendung via **Docker Compose** orchestriert. Dies startet sowohl das Backend (Python/Node) als auch das Frontend (Nginx) in optimierten Containern. + +### Starten der Anwendung + +1. Stellen Sie sicher, dass Docker und Docker Compose installiert sind. +2. Navigieren Sie in das Hauptverzeichnis. +3. Starten Sie den Stack: + +\`\`\`bash +docker-compose up -d --build +\`\`\` + +Der Build-Prozess kann beim ersten Mal einige Minuten dauern, da das Frontend kompiliert wird. + +### Zugriff + +* **Frontend:** Die Anwendung ist nun unter `http://:8085` erreichbar. +* **Backend:** Die API läuft intern und ist von außen nicht direkt erreichbar (Sicherheits-Feature). Der Frontend-Container leitet API-Anfragen automatisch weiter. + +### Einrichtung Online-Zugriff (Synology Reverse Proxy) + +Um die App sicher über das Internet (z.B. `https://market-intel.deine-domain.de`) erreichbar zu machen: + +1. Öffnen Sie auf der Synology Diskstation: **Systemsteuerung > Anmeldeportal > Erweitert > Reverse Proxy**. +2. Erstellen Sie eine neue Regel: + * **Quelle:** + * Protokoll: `HTTPS` + * Hostname: `market-intel.deine-domain.de` + * Port: `443` + * HSTS aktivieren: Ja + * **Ziel:** + * Protokoll: `HTTP` + * Hostname: `localhost` (oder Docker-IP) + * Port: `8085` (Port des Frontend-Containers) +3. (Optional) Weisen Sie im Tab "Sicherheit" ein Let's Encrypt Zertifikat zu. + +Die App ist nun weltweit sicher per HTTPS erreichbar. \ No newline at end of file