diff --git a/20250119_Logo_Botkozept.svg b/20250119_Logo_Botkozept.svg
new file mode 100644
index 0000000..8318377
--- /dev/null
+++ b/20250119_Logo_Botkozept.svg
@@ -0,0 +1,75 @@
+
+
+
+
diff --git a/BOTKONZEPT_README.md b/BOTKONZEPT_README.md
new file mode 100644
index 0000000..35f0f69
--- /dev/null
+++ b/BOTKONZEPT_README.md
@@ -0,0 +1,434 @@
+# 🤖 BotKonzept - SaaS Platform für KI-Chatbots
+
+## 📋 Übersicht
+
+BotKonzept ist eine vollständige SaaS-Plattform für KI-Chatbots mit automatischer Kundenregistrierung, Trial-Management und E-Mail-Automation.
+
+### Hauptfunktionen
+
+- ✅ **Automatische Kundenregistrierung** über Website
+- ✅ **Automatische LXC-Instanz-Erstellung** für jeden Kunden
+- ✅ **7-Tage-Trial** mit automatischen Upgrade-Angeboten
+- ✅ **E-Mail-Automation** (Tag 3, 5, 7)
+- ✅ **Rabatt-System** (30% → 15% → Normalpreis)
+- ✅ **Supabase-Integration** für Kunden-Management
+- ✅ **Stripe/PayPal** Payment-Integration
+- ✅ **DSGVO-konform** (Daten in Deutschland)
+
+## 🏗️ Architektur
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ BotKonzept Platform │
+├─────────────────────────────────────────────────────────────┤
+│ │
+│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
+│ │ Website │─────▶│ n8n Webhook │─────▶│ PVE20 │ │
+│ │ botkonzept.de│ │ Registration │ │ install.sh│ │
+│ └──────────────┘ └──────────────┘ └───────────┘ │
+│ │ │ │ │
+│ │ ▼ ▼ │
+│ │ ┌──────────────┐ ┌───────────┐ │
+│ │ │ Supabase │ │ LXC (CTID)│ │
+│ │ │ PostgreSQL │ │ n8n │ │
+│ │ │ Customers │ │ PostgREST│ │
+│ │ │ Instances │ │ Postgres │ │
+│ │ └──────────────┘ └───────────┘ │
+│ │ │ │
+│ ▼ ▼ │
+│ ┌──────────────┐ ┌──────────────┐ │
+│ │ Trial Mgmt │ │ Email Auto │ │
+│ │ Workflow │─────▶│ Day 3,5,7 │ │
+│ │ (Cron Daily) │ │ Postfix/SES │ │
+│ └──────────────┘ └──────────────┘ │
+│ │
+└─────────────────────────────────────────────────────────────┘
+```
+
+## 📁 Projekt-Struktur
+
+```
+customer-installer/
+├── botkonzept-website/ # Landing Page & Registrierung
+│ ├── index.html # Hauptseite
+│ ├── css/style.css # Styling
+│ └── js/main.js # JavaScript (Form-Handling)
+│
+├── sql/
+│ ├── botkonzept_schema.sql # Datenbank-Schema
+│ └── init_pgvector.sql # Vector-DB für RAG
+│
+├── BotKonzept-Customer-Registration-Workflow.json
+│ # n8n Workflow für Registrierung
+│
+├── BotKonzept-Trial-Management-Workflow.json
+│ # n8n Workflow für Trial-Management
+│
+├── install.sh # LXC-Installation
+├── libsupabase.sh # Helper-Funktionen
+├── setup_nginx_proxy.sh # NGINX Reverse Proxy
+└── BOTKONZEPT_README.md # Diese Datei
+```
+
+## 🚀 Installation & Setup
+
+### 1. Datenbank einrichten
+
+```bash
+# Supabase PostgreSQL Schema erstellen
+psql -U postgres -d customer < sql/botkonzept_schema.sql
+```
+
+### 2. n8n Workflows importieren
+
+1. Öffnen Sie n8n: `https://n8n.userman.de`
+2. Importieren Sie die Workflows:
+ - `BotKonzept-Customer-Registration-Workflow.json`
+ - `BotKonzept-Trial-Management-Workflow.json`
+3. Konfigurieren Sie die Credentials:
+ - **SSH (PVE20):** Private Key für Proxmox
+ - **PostgreSQL (Supabase):** Lokale Supabase-Instanz
+ - **SMTP (Postfix/SES):** E-Mail-Versand
+
+### 3. Website deployen
+
+```bash
+# Website-Dateien auf Webserver kopieren
+cd botkonzept-website
+rsync -avz . user@botkonzept.de:/var/www/botkonzept/
+
+# Oder lokal testen
+python3 -m http.server 8000
+# Öffnen: http://localhost:8000
+```
+
+### 4. Webhook-URL konfigurieren
+
+In `botkonzept-website/js/main.js`:
+
+```javascript
+const CONFIG = {
+ WEBHOOK_URL: 'https://n8n.userman.de/webhook/botkonzept-registration',
+ // ...
+};
+```
+
+## 📊 Customer Journey
+
+### Tag 0: Registrierung
+
+1. **Kunde registriert sich** auf botkonzept.de
+2. **n8n Webhook** empfängt Daten
+3. **Validierung** der Eingaben
+4. **Passwort generieren** (16 Zeichen)
+5. **Kunde in DB speichern** (Supabase)
+6. **LXC-Instanz erstellen** via `install.sh`
+7. **Instanz-Daten speichern** in DB
+8. **Willkommens-E-Mail** senden mit Zugangsdaten
+
+**E-Mail-Inhalt:**
+- Dashboard-URL
+- Login-Daten
+- Chat-Webhook-URL
+- Upload-Formular-URL
+- Quick-Start-Guide
+
+### Tag 3: Frühbucher-Angebot
+
+**Automatisch um 9:00 Uhr:**
+- **E-Mail:** "30% Frühbucher-Rabatt"
+- **Preis:** €34,30/Monat (statt €49)
+- **Ersparnis:** €176,40/Jahr
+- **Gültigkeit:** 48 Stunden
+
+### Tag 5: Erinnerung
+
+**Automatisch um 9:00 Uhr:**
+- **E-Mail:** "Nur noch 2 Tage - 15% Rabatt"
+- **Preis:** €41,65/Monat (statt €49)
+- **Ersparnis:** €88,20/Jahr
+- **Warnung:** Instanz wird bald gelöscht
+
+### Tag 7: Letzte Chance
+
+**Automatisch um 9:00 Uhr:**
+- **E-Mail:** "Trial endet heute"
+- **Preis:** €49/Monat (Normalpreis)
+- **Keine Rabatte** mehr verfügbar
+- **Dringlichkeit:** Instanz wird um Mitternacht gelöscht
+
+### Tag 8: Instanz löschen
+
+**Automatisch um 9:00 Uhr:**
+- **LXC-Instanz löschen** via `pct destroy`
+- **Status aktualisieren** in DB
+- **Goodbye-E-Mail** mit Feedback-Umfrage
+
+## 💰 Preis-Modell
+
+### Trial (7 Tage)
+- **Preis:** €0
+- **Features:** Voller Funktionsumfang
+- **Limit:** 100 Dokumente, 1.000 Nachrichten
+
+### Starter
+- **Normalpreis:** €49/Monat
+- **Tag 3 Rabatt:** €34,30/Monat (30% OFF)
+- **Tag 5 Rabatt:** €41,65/Monat (15% OFF)
+- **Features:**
+ - Unbegrenzte Dokumente
+ - 10.000 Nachrichten/Monat
+ - Prioritäts-Support
+ - Custom Branding
+ - Analytics Dashboard
+
+### Business
+- **Preis:** €149/Monat
+- **Features:**
+ - 50.000 Nachrichten/Monat
+ - Mehrere Chatbots
+ - API-Zugriff
+ - Dedizierter Support
+ - SLA-Garantie
+
+## 🔧 Technische Details
+
+### Datenbank-Schema
+
+**Haupttabellen:**
+- `customers` - Kundendaten
+- `instances` - LXC-Instanzen
+- `subscriptions` - Abonnements
+- `payments` - Zahlungen
+- `emails_sent` - E-Mail-Tracking
+- `usage_stats` - Nutzungsstatistiken
+- `audit_log` - Audit-Trail
+
+### n8n Workflows
+
+#### 1. Customer Registration Workflow
+
+**Trigger:** Webhook (POST /webhook/botkonzept-registration)
+
+**Schritte:**
+1. Validate Input
+2. Generate Password & Trial Date
+3. Create Customer in DB
+4. Create Customer Instance (SSH)
+5. Parse Install Output
+6. Save Instance to DB
+7. Send Welcome Email
+8. Log Email Sent
+9. Success Response
+
+#### 2. Trial Management Workflow
+
+**Trigger:** Cron (täglich 9:00 Uhr)
+
+**Schritte:**
+1. Get Trial Customers (SQL Query)
+2. Check Day 3/5/7/8
+3. Send entsprechende E-Mail
+4. Log Email Sent
+5. (Tag 8) Delete Instance
+
+### E-Mail-Templates
+
+Alle E-Mails sind:
+- ✅ **Responsive** (Mobile-optimiert)
+- ✅ **HTML-formatiert** mit Inline-CSS
+- ✅ **Branded** mit Logo und Farben
+- ✅ **CTA-optimiert** mit klaren Buttons
+- ✅ **Tracking-fähig** (Opens, Clicks)
+
+### Security
+
+- ✅ **HTTPS** für alle Verbindungen
+- ✅ **JWT-Tokens** für API-Authentifizierung
+- ✅ **Row Level Security** in Supabase
+- ✅ **Passwort-Hashing** (bcrypt)
+- ✅ **DSGVO-konform** (Daten in DE)
+- ✅ **Input-Validierung** auf allen Ebenen
+
+## 📧 E-Mail-Konfiguration
+
+### Postfix Gateway (OPNsense)
+
+```bash
+# SMTP-Server: 192.168.45.1
+# Port: 25 (intern)
+# Relay: Amazon SES
+```
+
+### Sendy.co Integration (optional)
+
+Für Newsletter und Marketing-E-Mails:
+
+```javascript
+// In js/main.js
+function subscribeNewsletter(email) {
+ const sendyUrl = 'https://sendy.userman.de/subscribe';
+ // ...
+}
+```
+
+## 💳 Payment-Integration
+
+### Stripe
+
+```javascript
+// Stripe Checkout Session erstellen
+const session = await stripe.checkout.sessions.create({
+ customer_email: customer.email,
+ line_items: [{
+ price: 'price_starter_monthly',
+ quantity: 1,
+ }],
+ mode: 'subscription',
+ success_url: 'https://botkonzept.de/success',
+ cancel_url: 'https://botkonzept.de/cancel',
+});
+```
+
+### PayPal
+
+```javascript
+// PayPal Subscription erstellen
+paypal.Buttons({
+ createSubscription: function(data, actions) {
+ return actions.subscription.create({
+ plan_id: 'P-STARTER-MONTHLY'
+ });
+ }
+}).render('#paypal-button-container');
+```
+
+## 📈 Analytics & Tracking
+
+### Google Analytics
+
+```html
+
+
+```
+
+### Conversion Tracking
+
+```javascript
+// In js/main.js
+function trackConversion(eventName, data) {
+ gtag('event', eventName, {
+ 'event_category': 'registration',
+ 'event_label': 'trial',
+ 'value': 0
+ });
+}
+```
+
+## 🧪 Testing
+
+### Lokales Testing
+
+```bash
+# Website lokal testen
+cd botkonzept-website
+python3 -m http.server 8000
+
+# n8n Workflow testen
+curl -X POST https://n8n.userman.de/webhook/botkonzept-registration \
+ -H "Content-Type: application/json" \
+ -d '{
+ "firstName": "Max",
+ "lastName": "Mustermann",
+ "email": "test@example.com",
+ "company": "Test GmbH"
+ }'
+```
+
+### Datenbank-Queries
+
+```sql
+-- Alle Trial-Kunden anzeigen
+SELECT * FROM customer_overview WHERE status = 'trial';
+
+-- E-Mails der letzten 7 Tage
+SELECT * FROM emails_sent WHERE sent_at >= NOW() - INTERVAL '7 days';
+
+-- Trials die bald ablaufen
+SELECT * FROM trials_expiring_soon;
+
+-- Revenue-Übersicht
+SELECT * FROM revenue_metrics;
+```
+
+## 🔄 Workflow-Verbesserungen
+
+### Vorschläge für Erweiterungen
+
+1. **A/B Testing**
+ - Verschiedene E-Mail-Varianten testen
+ - Conversion-Rates vergleichen
+
+2. **Personalisierung**
+ - Branchen-spezifische E-Mails
+ - Nutzungsbasierte Empfehlungen
+
+3. **Retargeting**
+ - Abgebrochene Registrierungen
+ - Reaktivierung inaktiver Kunden
+
+4. **Referral-Programm**
+ - Kunden werben Kunden
+ - Rabatte für Empfehlungen
+
+5. **Upselling**
+ - Automatische Upgrade-Vorschläge
+ - Feature-basierte Empfehlungen
+
+## 📞 Support & Kontakt
+
+- **Website:** https://botkonzept.de
+- **E-Mail:** support@botkonzept.de
+- **Dokumentation:** https://docs.botkonzept.de
+- **Status:** https://status.botkonzept.de
+
+## 📝 Lizenz
+
+Proprietär - Alle Rechte vorbehalten
+
+## 🎯 Roadmap
+
+### Q1 2025
+- [x] Website-Launch
+- [x] Automatische Registrierung
+- [x] Trial-Management
+- [ ] Stripe-Integration
+- [ ] PayPal-Integration
+
+### Q2 2025
+- [ ] Mobile App
+- [ ] White-Label-Option
+- [ ] API-Dokumentation
+- [ ] Marketplace für Templates
+
+### Q3 2025
+- [ ] Multi-Language Support
+- [ ] Advanced Analytics
+- [ ] Team-Features
+- [ ] Enterprise-Plan
+
+## 🙏 Credits
+
+Entwickelt mit:
+- **n8n** - Workflow-Automation
+- **Supabase** - Backend-as-a-Service
+- **Proxmox** - Virtualisierung
+- **PostgreSQL** - Datenbank
+- **PostgREST** - REST API
+- **Ollama** - LLM-Integration
+
+---
+
+**Version:** 1.0.0
+**Letzte Aktualisierung:** 25.01.2025
+**Autor:** MediaMetz
diff --git a/BotKonzept-Customer-Registration-Workflow.json b/BotKonzept-Customer-Registration-Workflow.json
new file mode 100644
index 0000000..1a43454
--- /dev/null
+++ b/BotKonzept-Customer-Registration-Workflow.json
@@ -0,0 +1,312 @@
+{
+ "name": "BotKonzept - Customer Registration & Trial Management",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "botkonzept-registration",
+ "responseMode": "responseNode",
+ "options": {}
+ },
+ "id": "webhook-registration",
+ "name": "Registration Webhook",
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 1.1,
+ "position": [250, 300],
+ "webhookId": "botkonzept-registration"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "string": [
+ {
+ "value1": "={{$json.body.email}}",
+ "operation": "isNotEmpty"
+ },
+ {
+ "value1": "={{$json.body.firstName}}",
+ "operation": "isNotEmpty"
+ },
+ {
+ "value1": "={{$json.body.lastName}}",
+ "operation": "isNotEmpty"
+ }
+ ]
+ }
+ },
+ "id": "validate-input",
+ "name": "Validate Input",
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 1,
+ "position": [450, 300]
+ },
+ {
+ "parameters": {
+ "operation": "insert",
+ "schema": "public",
+ "table": "customers",
+ "columns": "email,first_name,last_name,company,status,created_at,trial_end_date",
+ "additionalFields": {
+ "returnFields": "*"
+ }
+ },
+ "id": "create-customer",
+ "name": "Create Customer in DB",
+ "type": "n8n-nodes-base.postgres",
+ "typeVersion": 2.4,
+ "position": [650, 200],
+ "credentials": {
+ "postgres": {
+ "id": "supabase-local",
+ "name": "Supabase Local"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "=/root/customer-installer/install.sh --storage local-zfs --bridge vmbr0 --ip dhcp --vlan 90 --apt-proxy http://192.168.45.2:3142 --n8n-owner-email {{ $json.email }} --n8n-owner-pass \"{{ $('Generate-Password').item.json.password }}\"",
+ "cwd": "/root/customer-installer/"
+ },
+ "id": "create-instance",
+ "name": "Create Customer Instance",
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [850, 200],
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "pve20-ssh",
+ "name": "PVE20"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "// Parse installation output\nconst stdout = $input.item.json.stdout;\nconst installData = JSON.parse(stdout);\n\n// Add customer info\ninstallData.customer = {\n id: $('Create Customer in DB').item.json.id,\n email: $('Create Customer in DB').item.json.email,\n firstName: $('Create Customer in DB').item.json.first_name,\n lastName: $('Create Customer in DB').item.json.last_name,\n company: $('Create Customer in DB').item.json.company\n};\n\nreturn installData;"
+ },
+ "id": "parse-install-output",
+ "name": "Parse Install Output",
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [1050, 200]
+ },
+ {
+ "parameters": {
+ "operation": "insert",
+ "schema": "public",
+ "table": "instances",
+ "columns": "customer_id,ctid,hostname,ip,fqdn,status,credentials,created_at,trial_end_date",
+ "additionalFields": {}
+ },
+ "id": "save-instance",
+ "name": "Save Instance to DB",
+ "type": "n8n-nodes-base.postgres",
+ "typeVersion": 2.4,
+ "position": [1250, 200],
+ "credentials": {
+ "postgres": {
+ "id": "supabase-local",
+ "name": "Supabase Local"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "fromEmail": "noreply@botkonzept.de",
+ "toEmail": "={{ $json.customer.email }}",
+ "subject": "Willkommen bei BotKonzept - Ihre Instanz ist bereit! 🎉",
+ "emailType": "html",
+ "message": "=\n\n
\n \n \n\n\n \n \n \n
\n
Hallo {{ $json.customer.firstName }},
\n \n
vielen Dank für Ihre Registrierung! Ihre persönliche KI-Chatbot-Instanz wurde erfolgreich erstellt und ist jetzt einsatzbereit.
\n \n
\n \n
🚀 Nächste Schritte:
\n
\n - Einloggen: Klicken Sie auf den Link oben und loggen Sie sich ein
\n - Dokumente hochladen: Laden Sie Ihre PDFs, FAQs oder andere Dokumente hoch
\n - Chatbot testen: Testen Sie Ihren Chatbot direkt im Dashboard
\n - Code einbinden: Kopieren Sie den Widget-Code auf Ihre Website
\n
\n \n
Jetzt Dashboard öffnen →\n \n
\n
💰 Frühbucher-Angebot:
\n
Upgraden Sie in den nächsten 3 Tagen und erhalten Sie 30% Rabatt auf Ihr erstes Jahr!
\n
\n \n
Trial-Zeitraum: 7 Tage (bis {{ $json.trial_end_date }})
\n \n
Bei Fragen stehen wir Ihnen jederzeit zur Verfügung!
\n \n
Viel Erfolg mit Ihrem KI-Chatbot!
\n Ihr BotKonzept-Team
\n
\n \n \n
\n\n",
+ "options": {
+ "allowUnauthorizedCerts": false
+ }
+ },
+ "id": "send-welcome-email",
+ "name": "Send Welcome Email",
+ "type": "n8n-nodes-base.emailSend",
+ "typeVersion": 2.1,
+ "position": [1450, 200],
+ "credentials": {
+ "smtp": {
+ "id": "postfix-ses",
+ "name": "Postfix SES"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "operation": "insert",
+ "schema": "public",
+ "table": "emails_sent",
+ "columns": "customer_id,email_type,sent_at",
+ "additionalFields": {}
+ },
+ "id": "log-email",
+ "name": "Log Email Sent",
+ "type": "n8n-nodes-base.postgres",
+ "typeVersion": 2.4,
+ "position": [1650, 200],
+ "credentials": {
+ "postgres": {
+ "id": "supabase-local",
+ "name": "Supabase Local"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "respondWith": "json",
+ "responseBody": "={{ { \"success\": true, \"message\": \"Registrierung erfolgreich! Sie erhalten in Kürze eine E-Mail mit Ihren Zugangsdaten.\", \"customerId\": $json.customer.id, \"instanceUrl\": $json.urls.n8n_external } }}",
+ "options": {
+ "responseCode": 200
+ }
+ },
+ "id": "success-response",
+ "name": "Success Response",
+ "type": "n8n-nodes-base.respondToWebhook",
+ "typeVersion": 1,
+ "position": [1850, 200]
+ },
+ {
+ "parameters": {
+ "respondWith": "json",
+ "responseBody": "={{ { \"success\": false, \"error\": \"Ungültige Eingabedaten. Bitte überprüfen Sie Ihre Angaben.\" } }}",
+ "options": {
+ "responseCode": 400
+ }
+ },
+ "id": "error-response",
+ "name": "Error Response",
+ "type": "n8n-nodes-base.respondToWebhook",
+ "typeVersion": 1,
+ "position": [650, 400]
+ },
+ {
+ "parameters": {
+ "jsCode": "// Generate secure password\nconst length = 16;\nconst charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\nlet password = '';\n\nfor (let i = 0; i < length; i++) {\n const randomIndex = Math.floor(Math.random() * charset.length);\n password += charset[randomIndex];\n}\n\n// Calculate trial end date (7 days from now)\nconst trialEndDate = new Date();\ntrialEndDate.setDate(trialEndDate.getDate() + 7);\n\nreturn {\n password: password,\n trialEndDate: trialEndDate.toISOString(),\n email: $json.body.email,\n firstName: $json.body.firstName,\n lastName: $json.body.lastName,\n company: $json.body.company || null\n};"
+ },
+ "id": "generate-password",
+ "name": "Generate Password & Trial Date",
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [650, 100]
+ }
+ ],
+ "connections": {
+ "Registration Webhook": {
+ "main": [
+ [
+ {
+ "node": "Validate Input",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Validate Input": {
+ "main": [
+ [
+ {
+ "node": "Generate Password & Trial Date",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Error Response",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Generate Password & Trial Date": {
+ "main": [
+ [
+ {
+ "node": "Create Customer in DB",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Create Customer in DB": {
+ "main": [
+ [
+ {
+ "node": "Create Customer Instance",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Create Customer Instance": {
+ "main": [
+ [
+ {
+ "node": "Parse Install Output",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Parse Install Output": {
+ "main": [
+ [
+ {
+ "node": "Save Instance to DB",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Save Instance to DB": {
+ "main": [
+ [
+ {
+ "node": "Send Welcome Email",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Send Welcome Email": {
+ "main": [
+ [
+ {
+ "node": "Log Email Sent",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Log Email Sent": {
+ "main": [
+ [
+ {
+ "node": "Success Response",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "pinData": {},
+ "settings": {
+ "executionOrder": "v1"
+ },
+ "staticData": null,
+ "tags": [],
+ "triggerCount": 0,
+ "updatedAt": "2025-01-25T00:00:00.000Z",
+ "versionId": "1"
+}
diff --git a/BotKonzept-Trial-Management-Workflow.json b/BotKonzept-Trial-Management-Workflow.json
new file mode 100644
index 0000000..b154f6a
--- /dev/null
+++ b/BotKonzept-Trial-Management-Workflow.json
@@ -0,0 +1,122 @@
+{
+ "name": "BotKonzept - Trial Management & Email Automation",
+ "nodes": [
+ {
+ "parameters": {
+ "rule": {
+ "interval": [
+ {
+ "field": "cronExpression",
+ "expression": "0 9 * * *"
+ }
+ ]
+ }
+ },
+ "id": "daily-cron",
+ "name": "Daily at 9 AM",
+ "type": "n8n-nodes-base.scheduleTrigger",
+ "typeVersion": 1.1,
+ "position": [250, 300]
+ },
+ {
+ "parameters": {
+ "operation": "executeQuery",
+ "query": "SELECT c.id as customer_id, c.email, c.first_name, c.last_name, c.company, c.created_at, c.status, i.ctid, i.hostname, i.fqdn, i.trial_end_date, i.credentials, EXTRACT(DAY FROM (NOW() - c.created_at)) as days_since_registration FROM customers c JOIN instances i ON c.id = i.customer_id WHERE c.status = 'trial' AND i.status = 'active' AND c.created_at >= NOW() - INTERVAL '8 days'",
+ "additionalFields": {}
+ },
+ "id": "get-trial-customers",
+ "name": "Get Trial Customers",
+ "type": "n8n-nodes-base.postgres",
+ "typeVersion": 2.4,
+ "position": [450, 300],
+ "credentials": {
+ "postgres": {
+ "id": "supabase-local",
+ "name": "Supabase Local"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "number": [
+ {
+ "value1": "={{$json.days_since_registration}}",
+ "operation": "equal",
+ "value2": 3
+ }
+ ]
+ }
+ },
+ "id": "check-day-3",
+ "name": "Day 3?",
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 1,
+ "position": [650, 200]
+ },
+ {
+ "parameters": {
+ "operation": "insert",
+ "schema": "public",
+ "table": "emails_sent",
+ "columns": "customer_id,email_type,sent_at",
+ "additionalFields": {}
+ },
+ "id": "log-email-sent",
+ "name": "Log Email Sent",
+ "type": "n8n-nodes-base.postgres",
+ "typeVersion": 2.4,
+ "position": [1450, 200],
+ "credentials": {
+ "postgres": {
+ "id": "supabase-local",
+ "name": "Supabase Local"
+ }
+ }
+ }
+ ],
+ "connections": {
+ "Daily at 9 AM": {
+ "main": [
+ [
+ {
+ "node": "Get Trial Customers",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Get Trial Customers": {
+ "main": [
+ [
+ {
+ "node": "Day 3?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Day 3?": {
+ "main": [
+ [
+ {
+ "node": "Log Email Sent",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "pinData": {},
+ "settings": {
+ "executionOrder": "v1"
+ },
+ "staticData": null,
+ "tags": [],
+ "triggerCount": 0,
+ "updatedAt": "2025-01-25T00:00:00.000Z",
+ "versionId": "1"
+}
diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md
new file mode 100644
index 0000000..312e228
--- /dev/null
+++ b/DEPLOYMENT_CHECKLIST.md
@@ -0,0 +1,363 @@
+# 🚀 BotKonzept - Deployment Checkliste
+
+## ✅ Pre-Deployment
+
+### Infrastruktur
+- [ ] Proxmox VE20 läuft und ist erreichbar
+- [ ] Supabase PostgreSQL ist konfiguriert
+- [ ] n8n Instanz ist verfügbar
+- [ ] OPNsense NGINX Reverse Proxy ist konfiguriert
+- [ ] Postfix/SES E-Mail-Gateway funktioniert
+- [ ] DNS für botkonzept.de ist konfiguriert
+
+### Datenbank
+- [ ] PostgreSQL-Verbindung getestet
+- [ ] Schema `botkonzept_schema.sql` importiert
+- [ ] Tabellen erstellt (customers, instances, etc.)
+- [ ] Views erstellt (customer_overview, trials_expiring_soon)
+- [ ] Row Level Security aktiviert
+- [ ] Backup-Strategie definiert
+
+### n8n Workflows
+- [ ] Customer Registration Workflow importiert
+- [ ] Trial Management Workflow importiert
+- [ ] SSH-Credentials (PVE20) konfiguriert
+- [ ] PostgreSQL-Credentials konfiguriert
+- [ ] SMTP-Credentials konfiguriert
+- [ ] Webhooks aktiviert
+- [ ] Cron-Jobs aktiviert (täglich 9:00 Uhr)
+
+### Website
+- [ ] HTML/CSS/JS-Dateien geprüft
+- [ ] Logo (20250119_Logo_Botkozept.svg) vorhanden
+- [ ] Webhook-URL in main.js konfiguriert
+- [ ] SSL-Zertifikat installiert
+- [ ] HTTPS erzwungen
+- [ ] Cookie-Banner implementiert
+- [ ] Datenschutzerklärung vorhanden
+- [ ] Impressum vorhanden
+- [ ] AGB vorhanden
+
+## 🔧 Deployment Steps
+
+### 1. Datenbank Setup
+
+```bash
+# Verbindung testen
+psql -h 192.168.45.3 -U customer -d customer -c "SELECT 1"
+
+# Schema importieren
+psql -h 192.168.45.3 -U customer -d customer -f sql/botkonzept_schema.sql
+
+# Tabellen verifizieren
+psql -h 192.168.45.3 -U customer -d customer -c "\dt"
+```
+
+**Erwartetes Ergebnis:**
+- 7 Tabellen erstellt
+- 3 Views erstellt
+- Triggers aktiv
+
+### 2. n8n Workflows
+
+```bash
+# 1. n8n öffnen
+open https://n8n.userman.de
+
+# 2. Workflows importieren
+# - BotKonzept-Customer-Registration-Workflow.json
+# - BotKonzept-Trial-Management-Workflow.json
+
+# 3. Credentials konfigurieren
+# SSH (PVE20): /root/.ssh/id_rsa
+# PostgreSQL: 192.168.45.3:5432/customer
+# SMTP: Postfix Gateway
+```
+
+**Webhook-URLs:**
+- Registration: `https://n8n.userman.de/webhook/botkonzept-registration`
+- Test: `curl -X POST https://n8n.userman.de/webhook/botkonzept-registration -H "Content-Type: application/json" -d '{"test":true}'`
+
+### 3. Website Deployment
+
+```bash
+# Setup-Script ausführen
+chmod +x setup_botkonzept.sh
+./setup_botkonzept.sh
+
+# Oder manuell:
+sudo mkdir -p /var/www/botkonzept
+sudo cp -r botkonzept-website/* /var/www/botkonzept/
+sudo chown -R www-data:www-data /var/www/botkonzept
+```
+
+**NGINX-Konfiguration:**
+
+```nginx
+server {
+ listen 80;
+ server_name botkonzept.de www.botkonzept.de;
+ return 301 https://$server_name$request_uri;
+}
+
+server {
+ listen 443 ssl http2;
+ server_name botkonzept.de www.botkonzept.de;
+
+ ssl_certificate /etc/letsencrypt/live/botkonzept.de/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/botkonzept.de/privkey.pem;
+
+ root /var/www/botkonzept;
+ index index.html;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ # Security headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header X-XSS-Protection "1; mode=block" always;
+}
+```
+
+### 4. SSL-Zertifikat
+
+```bash
+# Let's Encrypt installieren
+sudo apt-get install certbot python3-certbot-nginx
+
+# Zertifikat erstellen
+sudo certbot --nginx -d botkonzept.de -d www.botkonzept.de
+
+# Auto-Renewal testen
+sudo certbot renew --dry-run
+```
+
+## ✅ Post-Deployment Tests
+
+### 1. Datenbank-Tests
+
+```sql
+-- Kunden-Tabelle testen
+INSERT INTO customers (email, first_name, last_name, status)
+VALUES ('test@example.com', 'Test', 'User', 'trial')
+RETURNING *;
+
+-- View testen
+SELECT * FROM customer_overview;
+
+-- Cleanup
+DELETE FROM customers WHERE email = 'test@example.com';
+```
+
+### 2. Workflow-Tests
+
+```bash
+# Registration Webhook testen
+curl -X POST https://n8n.userman.de/webhook/botkonzept-registration \
+ -H "Content-Type: application/json" \
+ -d '{
+ "firstName": "Max",
+ "lastName": "Mustermann",
+ "email": "test@example.com",
+ "company": "Test GmbH",
+ "terms": true
+ }'
+
+# Erwartete Antwort:
+# {"success": true, "message": "Registrierung erfolgreich!"}
+```
+
+### 3. Website-Tests
+
+- [ ] Homepage lädt (https://botkonzept.de)
+- [ ] Alle Bilder werden angezeigt
+- [ ] Navigation funktioniert
+- [ ] Formular wird angezeigt
+- [ ] Formular-Validierung funktioniert
+- [ ] Mobile-Ansicht korrekt
+- [ ] SSL-Zertifikat gültig
+- [ ] Keine Console-Errors
+
+### 4. E-Mail-Tests
+
+```bash
+# Test-E-Mail senden
+echo "Test" | mail -s "BotKonzept Test" test@example.com
+
+# Postfix-Logs prüfen
+tail -f /var/log/mail.log
+```
+
+### 5. End-to-End Test
+
+1. **Registrierung:**
+ - [ ] Formular ausfüllen
+ - [ ] Absenden
+ - [ ] Success-Message erscheint
+
+2. **Datenbank:**
+ - [ ] Kunde in `customers` Tabelle
+ - [ ] Instanz in `instances` Tabelle
+ - [ ] E-Mail in `emails_sent` Tabelle
+
+3. **E-Mail:**
+ - [ ] Willkommens-E-Mail erhalten
+ - [ ] Zugangsdaten korrekt
+ - [ ] Links funktionieren
+
+4. **Instanz:**
+ - [ ] LXC erstellt (pct list)
+ - [ ] n8n erreichbar
+ - [ ] Login funktioniert
+
+## 📊 Monitoring
+
+### Datenbank-Monitoring
+
+```sql
+-- Aktive Trials
+SELECT COUNT(*) FROM customers WHERE status = 'trial';
+
+-- Trials die heute ablaufen
+SELECT * FROM trials_expiring_soon WHERE days_remaining < 1;
+
+-- E-Mails der letzten 24h
+SELECT email_type, COUNT(*)
+FROM emails_sent
+WHERE sent_at >= NOW() - INTERVAL '24 hours'
+GROUP BY email_type;
+
+-- Revenue heute
+SELECT SUM(amount) FROM payments
+WHERE status = 'succeeded'
+AND paid_at::date = CURRENT_DATE;
+```
+
+### n8n-Monitoring
+
+- [ ] Workflow-Executions prüfen
+- [ ] Error-Rate überwachen
+- [ ] Execution-Time tracken
+
+### Server-Monitoring
+
+```bash
+# LXC-Container zählen
+pct list | grep -c "running"
+
+# Disk-Usage
+df -h
+
+# Memory-Usage
+free -h
+
+# Load Average
+uptime
+```
+
+## 🔒 Security Checklist
+
+- [ ] Firewall-Regeln konfiguriert
+- [ ] SSH nur mit Key-Auth
+- [ ] PostgreSQL nur intern erreichbar
+- [ ] n8n hinter Reverse Proxy
+- [ ] SSL/TLS erzwungen
+- [ ] Rate-Limiting aktiviert
+- [ ] CORS korrekt konfiguriert
+- [ ] Input-Validierung aktiv
+- [ ] SQL-Injection-Schutz
+- [ ] XSS-Schutz
+- [ ] CSRF-Schutz
+
+## 📝 Backup-Strategie
+
+### Datenbank-Backup
+
+```bash
+# Tägliches Backup
+0 2 * * * pg_dump -h 192.168.45.3 -U customer customer > /backup/botkonzept_$(date +\%Y\%m\%d).sql
+
+# Backup-Retention (30 Tage)
+find /backup -name "botkonzept_*.sql" -mtime +30 -delete
+```
+
+### LXC-Backup
+
+```bash
+# Proxmox Backup
+vzdump --mode snapshot --compress gzip --storage backup-storage
+```
+
+### Website-Backup
+
+```bash
+# Git-Repository
+cd /var/www/botkonzept
+git init
+git add .
+git commit -m "Website backup $(date)"
+git push origin main
+```
+
+## 🚨 Rollback-Plan
+
+### Bei Problemen mit Workflows
+
+1. Workflows deaktivieren
+2. Alte Version wiederherstellen
+3. Credentials prüfen
+4. Neu aktivieren
+
+### Bei Datenbank-Problemen
+
+```bash
+# Backup wiederherstellen
+psql -h 192.168.45.3 -U customer customer < /backup/botkonzept_YYYYMMDD.sql
+```
+
+### Bei Website-Problemen
+
+```bash
+# Alte Version wiederherstellen
+git checkout HEAD~1
+sudo cp -r botkonzept-website/* /var/www/botkonzept/
+```
+
+## 📞 Support-Kontakte
+
+- **Proxmox:** admin@userman.de
+- **n8n:** support@userman.de
+- **DNS:** dns@userman.de
+- **E-Mail:** postmaster@userman.de
+
+## ✅ Go-Live Checklist
+
+- [ ] Alle Tests bestanden
+- [ ] Monitoring aktiv
+- [ ] Backups konfiguriert
+- [ ] Team informiert
+- [ ] Dokumentation aktuell
+- [ ] Support-Prozesse definiert
+- [ ] Rollback-Plan getestet
+- [ ] Performance-Tests durchgeführt
+- [ ] Security-Audit durchgeführt
+- [ ] DSGVO-Compliance geprüft
+
+## 🎉 Post-Launch
+
+- [ ] Analytics einrichten (Google Analytics)
+- [ ] Conversion-Tracking aktivieren
+- [ ] A/B-Tests planen
+- [ ] Marketing-Kampagnen starten
+- [ ] Social Media ankündigen
+- [ ] Blog-Post veröffentlichen
+- [ ] Newsletter versenden
+
+---
+
+**Deployment-Datum:** _________________
+**Deployed von:** _________________
+**Version:** 1.0.0
+**Status:** ⬜ In Arbeit | ⬜ Bereit | ⬜ Live
diff --git a/Install-Workflow01.json b/Install-Workflow01.json
new file mode 100644
index 0000000..bc9d44e
--- /dev/null
+++ b/Install-Workflow01.json
@@ -0,0 +1,326 @@
+{
+ "name": "Install-Workflow",
+ "nodes": [
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "/root/customer-installer/install.sh --storage local-zfs --bridge vmbr0 --ip dhcp --vlan 90 --apt-proxy http://192.168.45.2:3142",
+ "cwd": "/root/customer-installer/"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 192,
+ 0
+ ],
+ "id": "9878a864-651e-4a53-abfc-b0bc2d2f2d15",
+ "name": "Start Installer 1",
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "bPl4nGXO7Iz4wJPJ",
+ "name": "PVE20"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "=./n8n_setup.sh --n8n_internal {{ $json.urls.n8n_internal }} --owner_email {{ $json.n8n.owner_email }} --owner_password \"{{ $json.n8n.owner_password }}\" --owner_first_name \"Max\" --owner_last_name \"Mustermann\" --timeout 30",
+ "cwd": "/root/customer-installer/"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 640,
+ 0
+ ],
+ "id": "62e1b647-7daa-445e-bf99-873efbe2bc94",
+ "name": "Setup n8n Owner",
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "bPl4nGXO7Iz4wJPJ",
+ "name": "PVE20"
+ }
+ },
+ "disabled": true
+ },
+ {
+ "parameters": {},
+ "type": "n8n-nodes-base.manualTrigger",
+ "typeVersion": 1,
+ "position": [
+ -32,
+ 0
+ ],
+ "id": "11aa3e6a-b20a-49b0-b6f9-4cec469c9916",
+ "name": "When clicking ‘Execute workflow’"
+ },
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "=bash setup_nginx_proxy.sh --ctid {{ $('install_JSON').item.json.ctid }} --hostname {{ $('install_JSON').item.json.hostname }} --fqdn {{ $('install_JSON').item.json.fqdn }} --backend-ip {{ $('install_JSON').item.json.ip }}",
+ "cwd": "/root/customer-installer/"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 1088,
+ 0
+ ],
+ "id": "176fd78c-9dd6-427b-a566-88dbf504347e",
+ "name": "setup_nginx_proxy",
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "bPl4nGXO7Iz4wJPJ",
+ "name": "PVE20"
+ }
+ },
+ "disabled": true
+ },
+ {
+ "parameters": {
+ "formTitle": "Delete",
+ "formFields": {
+ "values": [
+ {
+ "fieldLabel": "Host-Number",
+ "requiredField": true
+ }
+ ]
+ },
+ "options": {
+ "buttonLabel": "Löschen"
+ }
+ },
+ "type": "n8n-nodes-base.formTrigger",
+ "typeVersion": 2.5,
+ "position": [
+ -32,
+ 208
+ ],
+ "id": "4c9878ec-177c-4fbd-a83a-a3895ebd8193",
+ "name": "On form submission",
+ "webhookId": "12847d69-15c8-44e4-b595-645ff3109355"
+ },
+ {
+ "parameters": {
+ "jsCode": "// Code Node - JavaScript\nconst sshOutput = $input.all();\n\n// stdout-String parsen\nconst parsedData = JSON.parse(sshOutput[0].json.stdout);\n\nreturn [{\n json: parsedData\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 416,
+ 0
+ ],
+ "id": "67ace9d6-7ed2-4495-b3e6-6091fd252596",
+ "name": "install_JSON"
+ },
+ {
+ "parameters": {
+ "jsCode": "// Code Node - JavaScript\nconst sshOutput = $input.all();\n\n// stdout-String parsen\nconst parsedData = JSON.parse(sshOutput[0].json.stdout);\n\nreturn [{\n json: parsedData\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 864,
+ 0
+ ],
+ "id": "fc1b9d9f-5a70-476e-8ae2-4cfd81050527",
+ "name": "setupOwnerJSON",
+ "disabled": true
+ },
+ {
+ "parameters": {
+ "jsCode": "// Code Node - JavaScript\nconst sshOutput = $input.all();\n\n// stdout-String parsen\nconst parsedData = JSON.parse(sshOutput[0].json.stdout);\n\nreturn [{\n json: parsedData\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 1312,
+ 0
+ ],
+ "id": "86b70266-cafe-4a4f-98d1-20434f61061b",
+ "name": "setupProxyJSON",
+ "disabled": true
+ },
+ {
+ "parameters": {
+ "chatId": "26805429",
+ "text": "=Done.\nhttps://{{ $json.fqdn }}\nUsername: {{ $('install_JSON').item.json.n8n.owner_email }}\nPassword: {{ $('install_JSON').item.json.n8n.owner_password }}\nChat: {{ $('install_JSON').item.json.urls.chat_webhook }}",
+ "additionalFields": {
+ "appendAttribution": false
+ }
+ },
+ "type": "n8n-nodes-base.telegram",
+ "typeVersion": 1.2,
+ "position": [
+ 1536,
+ 0
+ ],
+ "id": "9e20ee75-c2ae-421f-ac4c-54f5643032f2",
+ "name": "Send a text message",
+ "webhookId": "55a97e93-a457-4bee-8b8f-3eea1ad62928",
+ "credentials": {
+ "telegramApi": {
+ "id": "7DYJfIx5JsxgKc0D",
+ "name": "LizTheLove_Bot"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "=/root/customer-installer/delete_nginx_proxy.sh --ctid {{ $('On form submission').item.json['Host-Number'] }}",
+ "cwd": "/root/customer-installer/"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 416,
+ 208
+ ],
+ "id": "34d50d3a-cdb8-4801-b54b-719ef60b4b63",
+ "name": "deleteProxy",
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "bPl4nGXO7Iz4wJPJ",
+ "name": "PVE20"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "authentication": "privateKey",
+ "command": "=pct stop {{ $json['Host-Number'] }} && pct destroy {{ $json['Host-Number'] }} ",
+ "cwd": "/root/customer-installer/"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 192,
+ 208
+ ],
+ "id": "4645ace7-30ef-4698-8288-065fe70ff9b0",
+ "name": "deleteLXC",
+ "credentials": {
+ "sshPrivateKey": {
+ "id": "bPl4nGXO7Iz4wJPJ",
+ "name": "PVE20"
+ }
+ }
+ }
+ ],
+ "pinData": {},
+ "connections": {
+ "Start Installer 1": {
+ "main": [
+ [
+ {
+ "node": "install_JSON",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Setup n8n Owner": {
+ "main": [
+ [
+ {
+ "node": "setupOwnerJSON",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "When clicking ‘Execute workflow’": {
+ "main": [
+ [
+ {
+ "node": "Start Installer 1",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "On form submission": {
+ "main": [
+ [
+ {
+ "node": "deleteLXC",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "install_JSON": {
+ "main": [
+ [
+ {
+ "node": "Setup n8n Owner",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "setupOwnerJSON": {
+ "main": [
+ [
+ {
+ "node": "setup_nginx_proxy",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "setup_nginx_proxy": {
+ "main": [
+ [
+ {
+ "node": "setupProxyJSON",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "setupProxyJSON": {
+ "main": [
+ [
+ {
+ "node": "Send a text message",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "deleteLXC": {
+ "main": [
+ [
+ {
+ "node": "deleteProxy",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "active": false,
+ "settings": {
+ "availableInMCP": false
+ },
+ "versionId": "7814a0dd-fae3-40e6-913b-f7b8bac10e81",
+ "meta": {
+ "templateCredsSetupCompleted": true,
+ "instanceId": "c832ea07b2e6ccb9d5832b81bb497b720b31ed50006898070951c4f6d209f426"
+ },
+ "id": "ba7BxTeeQif4zu2F",
+ "tags": []
+}
\ No newline at end of file
diff --git a/botkonzept-website/css/style.css b/botkonzept-website/css/style.css
new file mode 100644
index 0000000..bbd6c6a
--- /dev/null
+++ b/botkonzept-website/css/style.css
@@ -0,0 +1,884 @@
+/* ===================================
+ CSS Variables & Reset
+ =================================== */
+:root {
+ --primary-color: #2563eb;
+ --primary-dark: #1e40af;
+ --primary-light: #3b82f6;
+ --secondary-color: #10b981;
+ --text-dark: #1f2937;
+ --text-light: #6b7280;
+ --bg-light: #f9fafb;
+ --bg-white: #ffffff;
+ --border-color: #e5e7eb;
+ --success-color: #10b981;
+ --error-color: #ef4444;
+ --warning-color: #f59e0b;
+
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+ --font-mono: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
+
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
+
+ --radius-sm: 0.375rem;
+ --radius-md: 0.5rem;
+ --radius-lg: 0.75rem;
+ --radius-xl: 1rem;
+
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ font-family: var(--font-sans);
+ color: var(--text-dark);
+ line-height: 1.6;
+ background-color: var(--bg-white);
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+}
+
+a {
+ text-decoration: none;
+ color: inherit;
+ transition: var(--transition);
+}
+
+ul {
+ list-style: none;
+}
+
+/* ===================================
+ Container & Layout
+ =================================== */
+.container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+}
+
+section {
+ padding: 5rem 0;
+}
+
+.section-header {
+ text-align: center;
+ margin-bottom: 3rem;
+}
+
+.section-header h2 {
+ font-size: 2.5rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+ color: var(--text-dark);
+}
+
+.section-header p {
+ font-size: 1.25rem;
+ color: var(--text-light);
+ max-width: 600px;
+ margin: 0 auto;
+}
+
+/* ===================================
+ Navigation
+ =================================== */
+.navbar {
+ background: var(--bg-white);
+ box-shadow: var(--shadow-sm);
+ position: sticky;
+ top: 0;
+ z-index: 1000;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.nav-wrapper {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1rem 0;
+}
+
+.logo {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: var(--text-dark);
+}
+
+.logo img {
+ height: 40px;
+}
+
+.nav-menu {
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+}
+
+.nav-menu a {
+ color: var(--text-light);
+ font-weight: 500;
+ transition: var(--transition);
+}
+
+.nav-menu a:hover {
+ color: var(--primary-color);
+}
+
+.mobile-menu-toggle {
+ display: none;
+ flex-direction: column;
+ gap: 0.25rem;
+ background: none;
+ border: none;
+ cursor: pointer;
+ padding: 0.5rem;
+}
+
+.mobile-menu-toggle span {
+ width: 24px;
+ height: 2px;
+ background: var(--text-dark);
+ transition: var(--transition);
+}
+
+/* ===================================
+ Buttons
+ =================================== */
+.btn-primary,
+.btn-secondary {
+ display: inline-block;
+ padding: 0.75rem 1.5rem;
+ border-radius: var(--radius-md);
+ font-weight: 600;
+ text-align: center;
+ transition: var(--transition);
+ cursor: pointer;
+ border: none;
+ font-size: 1rem;
+}
+
+.btn-primary {
+ background: var(--primary-color);
+ color: white;
+}
+
+.btn-primary:hover {
+ background: var(--primary-dark);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-lg);
+}
+
+.btn-secondary {
+ background: transparent;
+ color: var(--primary-color);
+ border: 2px solid var(--primary-color);
+}
+
+.btn-secondary:hover {
+ background: var(--primary-color);
+ color: white;
+}
+
+.btn-large {
+ padding: 1rem 2rem;
+ font-size: 1.125rem;
+}
+
+.btn-block {
+ width: 100%;
+ display: block;
+}
+
+/* ===================================
+ Hero Section
+ =================================== */
+.hero {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 6rem 0;
+ position: relative;
+ overflow: hidden;
+}
+
+.hero::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: url('data:image/svg+xml,');
+ opacity: 0.3;
+}
+
+.hero-content {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+ align-items: center;
+ position: relative;
+ z-index: 1;
+}
+
+.hero h1 {
+ font-size: 3.5rem;
+ font-weight: 800;
+ line-height: 1.2;
+ margin-bottom: 1.5rem;
+}
+
+.hero-subtitle {
+ font-size: 1.25rem;
+ margin-bottom: 2rem;
+ opacity: 0.95;
+}
+
+.hero-cta {
+ display: flex;
+ gap: 1rem;
+ margin-bottom: 2rem;
+}
+
+.hero-features {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.feature-badge {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.95rem;
+ opacity: 0.9;
+}
+
+.feature-badge svg {
+ flex-shrink: 0;
+}
+
+/* Chatbot Demo */
+.chatbot-demo {
+ background: white;
+ border-radius: var(--radius-xl);
+ box-shadow: var(--shadow-xl);
+ overflow: hidden;
+ max-width: 400px;
+}
+
+.demo-header {
+ background: var(--primary-color);
+ color: white;
+ padding: 1rem;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.demo-dots {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.demo-dots span {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.3);
+}
+
+.demo-title {
+ font-weight: 600;
+}
+
+.demo-messages {
+ padding: 1.5rem;
+ background: #f9fafb;
+ min-height: 300px;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.message {
+ display: flex;
+ gap: 0.75rem;
+ align-items: flex-start;
+}
+
+.message.user {
+ flex-direction: row-reverse;
+}
+
+.message .avatar {
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ background: var(--primary-light);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+
+.message .bubble {
+ background: white;
+ padding: 0.75rem 1rem;
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-sm);
+ max-width: 70%;
+ color: var(--text-dark);
+}
+
+.message.user .bubble {
+ background: var(--primary-color);
+ color: white;
+}
+
+.demo-input {
+ padding: 1rem;
+ background: white;
+ border-top: 1px solid var(--border-color);
+ display: flex;
+ gap: 0.5rem;
+}
+
+.demo-input input {
+ flex: 1;
+ padding: 0.75rem;
+ border: 1px solid var(--border-color);
+ border-radius: var(--radius-md);
+ font-size: 0.95rem;
+}
+
+.demo-input button {
+ padding: 0.75rem 1.5rem;
+ background: var(--primary-color);
+ color: white;
+ border: none;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ font-size: 1.25rem;
+}
+
+/* ===================================
+ Features Section
+ =================================== */
+.features {
+ background: var(--bg-light);
+}
+
+.features-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 2rem;
+}
+
+.feature-card {
+ background: white;
+ padding: 2rem;
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-md);
+ transition: var(--transition);
+}
+
+.feature-card:hover {
+ transform: translateY(-5px);
+ box-shadow: var(--shadow-xl);
+}
+
+.feature-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+}
+
+.feature-card h3 {
+ font-size: 1.5rem;
+ margin-bottom: 1rem;
+ color: var(--text-dark);
+}
+
+.feature-card p {
+ color: var(--text-light);
+ line-height: 1.7;
+}
+
+/* ===================================
+ How It Works Section
+ =================================== */
+.steps {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 2rem;
+ margin-top: 3rem;
+}
+
+.step {
+ text-align: center;
+ position: relative;
+}
+
+.step-number {
+ width: 60px;
+ height: 60px;
+ background: var(--primary-color);
+ color: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.5rem;
+ font-weight: 700;
+ margin: 0 auto 1.5rem;
+}
+
+.step h3 {
+ font-size: 1.5rem;
+ margin-bottom: 1rem;
+}
+
+.step p {
+ color: var(--text-light);
+}
+
+/* ===================================
+ Pricing Section
+ =================================== */
+.pricing {
+ background: var(--bg-light);
+}
+
+.pricing-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 2rem;
+ margin-top: 3rem;
+}
+
+.pricing-card {
+ background: white;
+ border-radius: var(--radius-xl);
+ padding: 2.5rem;
+ box-shadow: var(--shadow-md);
+ transition: var(--transition);
+ position: relative;
+}
+
+.pricing-card:hover {
+ transform: translateY(-5px);
+ box-shadow: var(--shadow-xl);
+}
+
+.pricing-card.featured {
+ border: 3px solid var(--primary-color);
+ transform: scale(1.05);
+}
+
+.pricing-card .badge {
+ position: absolute;
+ top: -15px;
+ right: 20px;
+ background: var(--primary-color);
+ color: white;
+ padding: 0.5rem 1rem;
+ border-radius: var(--radius-md);
+ font-weight: 600;
+ font-size: 0.875rem;
+}
+
+.pricing-header h3 {
+ font-size: 1.5rem;
+ margin-bottom: 1rem;
+}
+
+.price {
+ display: flex;
+ align-items: baseline;
+ gap: 0.25rem;
+ margin-bottom: 0.5rem;
+}
+
+.price .currency {
+ font-size: 1.5rem;
+ font-weight: 600;
+}
+
+.price .amount {
+ font-size: 3.5rem;
+ font-weight: 800;
+ color: var(--primary-color);
+}
+
+.price .period {
+ font-size: 1.125rem;
+ color: var(--text-light);
+}
+
+.price-note {
+ font-size: 0.875rem;
+ color: var(--success-color);
+ font-weight: 600;
+ margin-bottom: 1.5rem;
+}
+
+.pricing-features {
+ margin: 2rem 0;
+}
+
+.pricing-features li {
+ padding: 0.75rem 0;
+ border-bottom: 1px solid var(--border-color);
+ color: var(--text-light);
+}
+
+.pricing-features li:last-child {
+ border-bottom: none;
+}
+
+/* ===================================
+ Trial Registration Section
+ =================================== */
+.trial-registration {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+}
+
+.trial-content {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+ align-items: center;
+}
+
+.trial-info h2 {
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
+}
+
+.trial-info p {
+ font-size: 1.25rem;
+ margin-bottom: 2rem;
+ opacity: 0.95;
+}
+
+.trial-benefits {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.trial-benefits li {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ font-size: 1.125rem;
+}
+
+.trial-benefits svg {
+ flex-shrink: 0;
+ color: var(--success-color);
+}
+
+.trial-form-wrapper {
+ background: white;
+ border-radius: var(--radius-xl);
+ padding: 2.5rem;
+ box-shadow: var(--shadow-xl);
+}
+
+.trial-form h3 {
+ color: var(--text-dark);
+ font-size: 1.75rem;
+ margin-bottom: 1.5rem;
+}
+
+.form-group {
+ margin-bottom: 1.5rem;
+}
+
+.form-group label {
+ display: block;
+ margin-bottom: 0.5rem;
+ color: var(--text-dark);
+ font-weight: 500;
+}
+
+.form-group input {
+ width: 100%;
+ padding: 0.75rem;
+ border: 1px solid var(--border-color);
+ border-radius: var(--radius-md);
+ font-size: 1rem;
+ transition: var(--transition);
+}
+
+.form-group input:focus {
+ outline: none;
+ border-color: var(--primary-color);
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
+}
+
+.form-group.checkbox {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+}
+
+.form-group.checkbox input {
+ width: auto;
+ margin-top: 0.25rem;
+}
+
+.form-group.checkbox label {
+ margin: 0;
+ font-weight: 400;
+ font-size: 0.95rem;
+}
+
+.form-group.checkbox a {
+ color: var(--primary-color);
+ text-decoration: underline;
+}
+
+.form-note {
+ font-size: 0.875rem;
+ color: var(--text-light);
+ text-align: center;
+ margin-top: 1rem;
+}
+
+.btn-loading {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+}
+
+.spinner {
+ animation: spin 1s linear infinite;
+}
+
+.spinner circle {
+ stroke-dasharray: 90, 150;
+ stroke-dashoffset: 0;
+ stroke-linecap: round;
+}
+
+@keyframes spin {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* Success Message */
+.success-message {
+ text-align: center;
+ padding: 2rem;
+}
+
+.success-icon {
+ width: 80px;
+ height: 80px;
+ background: var(--success-color);
+ color: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 3rem;
+ margin: 0 auto 1.5rem;
+}
+
+.success-message h3 {
+ color: var(--text-dark);
+ font-size: 1.75rem;
+ margin-bottom: 1rem;
+}
+
+.success-message p {
+ color: var(--text-light);
+ margin-bottom: 1.5rem;
+}
+
+.success-details {
+ background: var(--bg-light);
+ padding: 1.5rem;
+ border-radius: var(--radius-md);
+ text-align: left;
+}
+
+.success-details p {
+ color: var(--text-dark);
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.success-details ol {
+ list-style: decimal;
+ padding-left: 1.5rem;
+ color: var(--text-light);
+}
+
+.success-details li {
+ margin-bottom: 0.5rem;
+}
+
+/* ===================================
+ FAQ Section
+ =================================== */
+.faq-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
+ gap: 2rem;
+}
+
+.faq-item {
+ background: white;
+ padding: 2rem;
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-md);
+}
+
+.faq-item h3 {
+ font-size: 1.25rem;
+ margin-bottom: 1rem;
+ color: var(--text-dark);
+}
+
+.faq-item p {
+ color: var(--text-light);
+ line-height: 1.7;
+}
+
+/* ===================================
+ Footer
+ =================================== */
+.footer {
+ background: var(--text-dark);
+ color: white;
+ padding: 3rem 0 1.5rem;
+}
+
+.footer-content {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 2rem;
+ margin-bottom: 2rem;
+}
+
+.footer-section h4 {
+ margin-bottom: 1rem;
+ font-size: 1.125rem;
+}
+
+.footer-section p {
+ opacity: 0.8;
+ margin-top: 0.5rem;
+}
+
+.footer-section ul {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.footer-section a {
+ opacity: 0.8;
+ transition: var(--transition);
+}
+
+.footer-section a:hover {
+ opacity: 1;
+ color: var(--primary-light);
+}
+
+.footer-bottom {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ padding-top: 1.5rem;
+ text-align: center;
+ opacity: 0.8;
+}
+
+/* ===================================
+ Responsive Design
+ =================================== */
+@media (max-width: 768px) {
+ .nav-menu {
+ display: none;
+ }
+
+ .mobile-menu-toggle {
+ display: flex;
+ }
+
+ .hero-content,
+ .trial-content {
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ }
+
+ .hero h1 {
+ font-size: 2.5rem;
+ }
+
+ .hero-cta {
+ flex-direction: column;
+ }
+
+ .section-header h2 {
+ font-size: 2rem;
+ }
+
+ .steps {
+ grid-template-columns: 1fr;
+ }
+
+ .pricing-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .pricing-card.featured {
+ transform: scale(1);
+ }
+
+ .faq-grid {
+ grid-template-columns: 1fr;
+ }
+}
+
+@media (max-width: 480px) {
+ .hero h1 {
+ font-size: 2rem;
+ }
+
+ .hero-subtitle {
+ font-size: 1rem;
+ }
+
+ .section-header h2 {
+ font-size: 1.75rem;
+ }
+
+ .trial-form-wrapper {
+ padding: 1.5rem;
+ }
+}
diff --git a/botkonzept-website/index.html b/botkonzept-website/index.html
new file mode 100644
index 0000000..18983d6
--- /dev/null
+++ b/botkonzept-website/index.html
@@ -0,0 +1,417 @@
+
+
+
+
+
+ BotKonzept - KI-Chatbot für Ihre Website in 7 Tagen kostenlos testen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Ihr KI-Chatbot in Minuten einsatzbereit
+
+ Verwandeln Sie Ihre Dokumente in einen intelligenten Chatbot.
+ Keine Programmierung erforderlich. 7 Tage kostenlos testen.
+
+
+
+
+
+
Keine Kreditkarte erforderlich
+
+
+
+
In 5 Minuten eingerichtet
+
+
+
+
+
+
+
+
+
+
🤖
+
Hallo! Wie kann ich Ihnen helfen?
+
+
+
Was sind Ihre Öffnungszeiten?
+
👤
+
+
+
🤖
+
Wir sind Mo-Fr von 9-18 Uhr für Sie da!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
📄
+
Dokument-Upload
+
Laden Sie PDFs, Word-Dokumente oder Texte hoch. Ihr Chatbot lernt automatisch aus Ihren Inhalten.
+
+
+
🧠
+
RAG-Technologie
+
Modernste Retrieval-Augmented Generation für präzise und kontextbezogene Antworten.
+
+
+
⚡
+
Blitzschnelle Integration
+
Ein einfacher Code-Snippet - fertig! Ihr Chatbot ist in Minuten auf Ihrer Website.
+
+
+
🎨
+
Anpassbares Design
+
Passen Sie Farben, Logo und Texte an Ihre Marke an. Kein Entwickler erforderlich.
+
+
+
📊
+
Analytics & Insights
+
Verstehen Sie Ihre Kunden besser mit detaillierten Statistiken und Gesprächsverläufen.
+
+
+
🔒
+
DSGVO-konform
+
Ihre Daten bleiben in Deutschland. Volle DSGVO-Konformität garantiert.
+
+
+
+
+
+
+
+
+
+
+
+
1
+
+
Registrieren
+
Erstellen Sie Ihr kostenloses Testkonto in wenigen Sekunden. Keine Kreditkarte erforderlich.
+
+
+
+
2
+
+
Dokumente hochladen
+
Laden Sie Ihre PDFs, FAQs oder andere Dokumente hoch. Unser System verarbeitet sie automatisch.
+
+
+
+
3
+
+
Code einbinden
+
Kopieren Sie den generierten Code-Snippet und fügen Sie ihn auf Ihrer Website ein.
+
+
+
+
4
+
+
Fertig!
+
Ihr KI-Chatbot ist live und beantwortet Kundenanfragen rund um die Uhr.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - ✓ Voller Funktionsumfang
+ - ✓ Bis zu 100 Dokumente
+ - ✓ 1.000 Nachrichten/Monat
+ - ✓ E-Mail-Support
+ - ✓ Keine Kreditkarte erforderlich
+
+
Jetzt starten
+
+
+
Beliebt
+
+
+ - ✓ Alle Trial-Features
+ - ✓ Unbegrenzte Dokumente
+ - ✓ 10.000 Nachrichten/Monat
+ - ✓ Prioritäts-Support
+ - ✓ Custom Branding
+ - ✓ Analytics Dashboard
+
+
Jetzt upgraden
+
+
+
+
+ - ✓ Alle Starter-Features
+ - ✓ 50.000 Nachrichten/Monat
+ - ✓ Mehrere Chatbots
+ - ✓ API-Zugriff
+ - ✓ Dedizierter Support
+ - ✓ SLA-Garantie
+
+
Kontakt aufnehmen
+
+
+
+
+
+
+
+
+
+
+
Starten Sie Ihren 7-Tage-Test
+
Keine Kreditkarte erforderlich. Voller Funktionsumfang. Jederzeit kündbar.
+
+ -
+
+ Sofortiger Zugang zu Ihrer Instanz
+
+ -
+
+ Persönliche Einrichtungs-Hilfe
+
+ -
+
+ Exklusive Frühbucher-Rabatte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Brauche ich technische Kenntnisse?
+
Nein! Sie müssen nur einen Code-Snippet auf Ihrer Website einfügen können. Alles andere übernehmen wir für Sie.
+
+
+
Wie lange dauert die Einrichtung?
+
Nach der Registrierung ist Ihre Instanz in ca. 5 Minuten einsatzbereit. Das Hochladen von Dokumenten dauert je nach Menge 1-10 Minuten.
+
+
+
Kann ich jederzeit kündigen?
+
Ja, Sie können jederzeit kündigen. Es gibt keine Mindestlaufzeit und keine versteckten Kosten.
+
+
+
Wo werden meine Daten gespeichert?
+
Alle Daten werden in Deutschland auf DSGVO-konformen Servern gespeichert. Ihre Daten gehören Ihnen.
+
+
+
Welche Sprachen werden unterstützt?
+
Der Chatbot unterstützt Deutsch, Englisch und viele weitere Sprachen. Die KI erkennt die Sprache automatisch.
+
+
+
Was passiert nach dem Trial?
+
Sie erhalten am Tag 3, 5 und 7 E-Mails mit Upgrade-Angeboten. Wenn Sie nicht upgraden, wird Ihre Instanz nach 7 Tagen gelöscht.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/botkonzept-website/js/main.js b/botkonzept-website/js/main.js
new file mode 100644
index 0000000..f00e875
--- /dev/null
+++ b/botkonzept-website/js/main.js
@@ -0,0 +1,388 @@
+// BotKonzept Website - Main JavaScript
+// =====================================
+
+// Configuration
+const CONFIG = {
+ // n8n Webhook URL für Registrierung (wird später konfiguriert)
+ WEBHOOK_URL: 'https://n8n.userman.de/webhook/botkonzept-registration',
+ // Supabase URL (lokale Instanz)
+ SUPABASE_URL: 'http://192.168.45.3:3000',
+ SUPABASE_ANON_KEY: 'your-anon-key-here'
+};
+
+// =====================================
+// Mobile Menu Toggle
+// =====================================
+document.addEventListener('DOMContentLoaded', function() {
+ const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
+ const navMenu = document.querySelector('.nav-menu');
+
+ if (mobileMenuToggle) {
+ mobileMenuToggle.addEventListener('click', function() {
+ navMenu.classList.toggle('active');
+ this.classList.toggle('active');
+ });
+ }
+
+ // Close mobile menu when clicking on a link
+ const navLinks = document.querySelectorAll('.nav-menu a');
+ navLinks.forEach(link => {
+ link.addEventListener('click', function() {
+ navMenu.classList.remove('active');
+ mobileMenuToggle.classList.remove('active');
+ });
+ });
+});
+
+// =====================================
+// Smooth Scroll for Anchor Links
+// =====================================
+document.querySelectorAll('a[href^="#"]').forEach(anchor => {
+ anchor.addEventListener('click', function (e) {
+ e.preventDefault();
+ const target = document.querySelector(this.getAttribute('href'));
+ if (target) {
+ const offset = 80; // Navbar height
+ const targetPosition = target.offsetTop - offset;
+ window.scrollTo({
+ top: targetPosition,
+ behavior: 'smooth'
+ });
+ }
+ });
+});
+
+// =====================================
+// Trial Registration Form
+// =====================================
+const trialForm = document.getElementById('trialForm');
+const successMessage = document.getElementById('successMessage');
+
+if (trialForm) {
+ trialForm.addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ // Get form data
+ const formData = {
+ firstName: document.getElementById('firstName').value.trim(),
+ lastName: document.getElementById('lastName').value.trim(),
+ email: document.getElementById('email').value.trim().toLowerCase(),
+ company: document.getElementById('company').value.trim() || null,
+ terms: document.getElementById('terms').checked,
+ registeredAt: new Date().toISOString(),
+ source: 'website',
+ utmSource: getUrlParameter('utm_source') || null,
+ utmMedium: getUrlParameter('utm_medium') || null,
+ utmCampaign: getUrlParameter('utm_campaign') || null
+ };
+
+ // Validate
+ if (!formData.firstName || !formData.lastName || !formData.email) {
+ showError('Bitte füllen Sie alle Pflichtfelder aus.');
+ return;
+ }
+
+ if (!validateEmail(formData.email)) {
+ showError('Bitte geben Sie eine gültige E-Mail-Adresse ein.');
+ return;
+ }
+
+ if (!formData.terms) {
+ showError('Bitte akzeptieren Sie die AGB und Datenschutzerklärung.');
+ return;
+ }
+
+ // Show loading state
+ const submitButton = trialForm.querySelector('button[type="submit"]');
+ const btnText = submitButton.querySelector('.btn-text');
+ const btnLoading = submitButton.querySelector('.btn-loading');
+
+ submitButton.disabled = true;
+ btnText.style.display = 'none';
+ btnLoading.style.display = 'flex';
+
+ try {
+ // Send to n8n webhook
+ const response = await fetch(CONFIG.WEBHOOK_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(formData)
+ });
+
+ if (!response.ok) {
+ throw new Error('Registrierung fehlgeschlagen');
+ }
+
+ const result = await response.json();
+
+ // Show success message
+ trialForm.style.display = 'none';
+ successMessage.style.display = 'block';
+
+ // Track conversion (Google Analytics, Facebook Pixel, etc.)
+ trackConversion('trial_registration', formData);
+
+ // Scroll to success message
+ successMessage.scrollIntoView({ behavior: 'smooth', block: 'center' });
+
+ } catch (error) {
+ console.error('Registration error:', error);
+ showError('Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut oder kontaktieren Sie uns direkt.');
+
+ // Reset button state
+ submitButton.disabled = false;
+ btnText.style.display = 'inline';
+ btnLoading.style.display = 'none';
+ }
+ });
+}
+
+// =====================================
+// Helper Functions
+// =====================================
+
+function validateEmail(email) {
+ const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ return re.test(email);
+}
+
+function showError(message) {
+ // Create or update error message
+ let errorDiv = document.querySelector('.form-error');
+
+ if (!errorDiv) {
+ errorDiv = document.createElement('div');
+ errorDiv.className = 'form-error';
+ errorDiv.style.cssText = `
+ background: #fee2e2;
+ border: 1px solid #ef4444;
+ color: #991b1b;
+ padding: 1rem;
+ border-radius: 0.5rem;
+ margin-bottom: 1rem;
+ font-size: 0.95rem;
+ `;
+ trialForm.insertBefore(errorDiv, trialForm.firstChild);
+ }
+
+ errorDiv.textContent = message;
+ errorDiv.scrollIntoView({ behavior: 'smooth', block: 'center' });
+
+ // Remove after 5 seconds
+ setTimeout(() => {
+ errorDiv.remove();
+ }, 5000);
+}
+
+function getUrlParameter(name) {
+ const urlParams = new URLSearchParams(window.location.search);
+ return urlParams.get(name);
+}
+
+function trackConversion(eventName, data) {
+ // Google Analytics
+ if (typeof gtag !== 'undefined') {
+ gtag('event', eventName, {
+ 'event_category': 'registration',
+ 'event_label': 'trial',
+ 'value': 0
+ });
+ }
+
+ // Facebook Pixel
+ if (typeof fbq !== 'undefined') {
+ fbq('track', 'Lead', {
+ content_name: 'Trial Registration',
+ content_category: 'Registration'
+ });
+ }
+
+ // Custom tracking
+ console.log('Conversion tracked:', eventName, data);
+}
+
+// =====================================
+// Scroll Animations
+// =====================================
+const observerOptions = {
+ threshold: 0.1,
+ rootMargin: '0px 0px -50px 0px'
+};
+
+const observer = new IntersectionObserver(function(entries) {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ entry.target.classList.add('animate-in');
+ observer.unobserve(entry.target);
+ }
+ });
+}, observerOptions);
+
+// Observe elements for animation
+document.addEventListener('DOMContentLoaded', function() {
+ const animateElements = document.querySelectorAll('.feature-card, .step, .pricing-card, .faq-item');
+ animateElements.forEach(el => {
+ el.style.opacity = '0';
+ el.style.transform = 'translateY(20px)';
+ el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
+ observer.observe(el);
+ });
+});
+
+// Add CSS for animation
+const style = document.createElement('style');
+style.textContent = `
+ .animate-in {
+ opacity: 1 !important;
+ transform: translateY(0) !important;
+ }
+`;
+document.head.appendChild(style);
+
+// =====================================
+// Pricing Calculator (Optional)
+// =====================================
+function calculatePricing(plan, discount = 0) {
+ const prices = {
+ trial: 0,
+ starter: 49,
+ business: 149
+ };
+
+ const basePrice = prices[plan] || 0;
+ const discountedPrice = basePrice * (1 - discount / 100);
+
+ return {
+ basePrice,
+ discount,
+ discountedPrice,
+ savings: basePrice - discountedPrice
+ };
+}
+
+// =====================================
+// FAQ Accordion (Optional Enhancement)
+// =====================================
+document.querySelectorAll('.faq-item').forEach(item => {
+ item.addEventListener('click', function() {
+ this.classList.toggle('active');
+ });
+});
+
+// =====================================
+// Newsletter Subscription (Optional)
+// =====================================
+function subscribeNewsletter(email) {
+ // Integration mit Sendy.co
+ const sendyUrl = 'https://sendy.userman.de/subscribe';
+
+ const formData = new FormData();
+ formData.append('email', email);
+ formData.append('list', 'your-list-id');
+ formData.append('boolean', 'true');
+
+ return fetch(sendyUrl, {
+ method: 'POST',
+ body: formData
+ });
+}
+
+// =====================================
+// Live Chat Widget Integration (Optional)
+// =====================================
+function initializeChatWidget() {
+ // Hier kann später der eigene BotKonzept-Chatbot integriert werden
+ console.log('Chat widget initialized');
+}
+
+// =====================================
+// A/B Testing Helper (Optional)
+// =====================================
+function getABTestVariant() {
+ const variants = ['A', 'B'];
+ const stored = localStorage.getItem('ab_variant');
+
+ if (stored) {
+ return stored;
+ }
+
+ const variant = variants[Math.floor(Math.random() * variants.length)];
+ localStorage.setItem('ab_variant', variant);
+ return variant;
+}
+
+// =====================================
+// Cookie Consent (DSGVO)
+// =====================================
+function showCookieConsent() {
+ const consent = localStorage.getItem('cookie_consent');
+
+ if (!consent) {
+ const banner = document.createElement('div');
+ banner.className = 'cookie-banner';
+ banner.innerHTML = `
+
+
Wir verwenden Cookies, um Ihre Erfahrung zu verbessern.
+ Mehr erfahren
+
+
+ `;
+ banner.style.cssText = `
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #1f2937;
+ color: white;
+ padding: 1.5rem;
+ z-index: 9999;
+ box-shadow: 0 -4px 6px rgba(0,0,0,0.1);
+ `;
+ document.body.appendChild(banner);
+ }
+}
+
+function acceptCookies() {
+ localStorage.setItem('cookie_consent', 'true');
+ document.querySelector('.cookie-banner').remove();
+}
+
+// Show cookie consent on page load
+document.addEventListener('DOMContentLoaded', showCookieConsent);
+
+// =====================================
+// Performance Monitoring
+// =====================================
+if ('PerformanceObserver' in window) {
+ const observer = new PerformanceObserver((list) => {
+ for (const entry of list.getEntries()) {
+ console.log('Performance:', entry.name, entry.duration);
+ }
+ });
+ observer.observe({ entryTypes: ['measure', 'navigation'] });
+}
+
+// =====================================
+// Error Tracking
+// =====================================
+window.addEventListener('error', function(e) {
+ console.error('Global error:', e.error);
+ // Hier könnte Sentry oder ähnliches integriert werden
+});
+
+window.addEventListener('unhandledrejection', function(e) {
+ console.error('Unhandled promise rejection:', e.reason);
+});
+
+// =====================================
+// Export for testing
+// =====================================
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = {
+ validateEmail,
+ calculatePricing,
+ getUrlParameter
+ };
+}
diff --git a/setup_botkonzept.sh b/setup_botkonzept.sh
new file mode 100755
index 0000000..8c2ccde
--- /dev/null
+++ b/setup_botkonzept.sh
@@ -0,0 +1,298 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+# =====================================================
+# BotKonzept Setup Script
+# =====================================================
+# This script sets up the complete BotKonzept platform
+# including database, n8n workflows, and website
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# Color codes
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Configuration
+SUPABASE_HOST="${SUPABASE_HOST:-192.168.45.3}"
+SUPABASE_PORT="${SUPABASE_PORT:-5432}"
+SUPABASE_DB="${SUPABASE_DB:-customer}"
+SUPABASE_USER="${SUPABASE_USER:-customer}"
+SUPABASE_PASSWORD="${SUPABASE_PASSWORD:-}"
+
+N8N_HOST="${N8N_HOST:-n8n.userman.de}"
+WEBSITE_DIR="${WEBSITE_DIR:-/var/www/botkonzept}"
+
+print_header() {
+ echo -e "${BLUE}========================================${NC}"
+ echo -e "${BLUE}$1${NC}"
+ echo -e "${BLUE}========================================${NC}"
+ echo ""
+}
+
+print_success() {
+ echo -e "${GREEN}✓${NC} $1"
+}
+
+print_error() {
+ echo -e "${RED}✗${NC} $1"
+}
+
+print_info() {
+ echo -e "${BLUE}ℹ${NC} $1"
+}
+
+print_warning() {
+ echo -e "${YELLOW}⚠${NC} $1"
+}
+
+# Check prerequisites
+check_prerequisites() {
+ print_header "Checking Prerequisites"
+
+ local missing=0
+
+ # Check psql
+ if command -v psql >/dev/null 2>&1; then
+ print_success "PostgreSQL client installed"
+ else
+ print_error "PostgreSQL client not found"
+ missing=1
+ fi
+
+ # Check curl
+ if command -v curl >/dev/null 2>&1; then
+ print_success "curl installed"
+ else
+ print_error "curl not found"
+ missing=1
+ fi
+
+ # Check jq
+ if command -v jq >/dev/null 2>&1; then
+ print_success "jq installed"
+ else
+ print_warning "jq not found (optional, but recommended)"
+ fi
+
+ if [[ $missing -eq 1 ]]; then
+ print_error "Missing required dependencies. Please install them first."
+ exit 1
+ fi
+
+ echo ""
+}
+
+# Setup database
+setup_database() {
+ print_header "Setting up Database"
+
+ if [[ -z "$SUPABASE_PASSWORD" ]]; then
+ print_error "SUPABASE_PASSWORD not set"
+ echo "Please set the password:"
+ echo " export SUPABASE_PASSWORD='your-password'"
+ exit 1
+ fi
+
+ print_info "Connecting to PostgreSQL at ${SUPABASE_HOST}:${SUPABASE_PORT}"
+
+ # Test connection
+ if PGPASSWORD="$SUPABASE_PASSWORD" psql -h "$SUPABASE_HOST" -p "$SUPABASE_PORT" -U "$SUPABASE_USER" -d "$SUPABASE_DB" -c "SELECT 1" >/dev/null 2>&1; then
+ print_success "Database connection successful"
+ else
+ print_error "Cannot connect to database"
+ exit 1
+ fi
+
+ # Create schema
+ print_info "Creating BotKonzept schema..."
+ if PGPASSWORD="$SUPABASE_PASSWORD" psql -h "$SUPABASE_HOST" -p "$SUPABASE_PORT" -U "$SUPABASE_USER" -d "$SUPABASE_DB" -f "${SCRIPT_DIR}/sql/botkonzept_schema.sql" >/dev/null 2>&1; then
+ print_success "Schema created successfully"
+ else
+ print_error "Failed to create schema"
+ exit 1
+ fi
+
+ # Verify tables
+ print_info "Verifying tables..."
+ local tables=$(PGPASSWORD="$SUPABASE_PASSWORD" psql -h "$SUPABASE_HOST" -p "$SUPABASE_PORT" -U "$SUPABASE_USER" -d "$SUPABASE_DB" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public' AND table_name IN ('customers', 'instances', 'subscriptions', 'payments', 'emails_sent')")
+
+ if [[ "$tables" -eq 5 ]]; then
+ print_success "All tables created successfully"
+ else
+ print_warning "Expected 5 tables, found $tables"
+ fi
+
+ echo ""
+}
+
+# Setup n8n workflows
+setup_n8n_workflows() {
+ print_header "Setting up n8n Workflows"
+
+ print_info "n8n workflows need to be imported manually:"
+ echo ""
+ echo "1. Open n8n: https://${N8N_HOST}"
+ echo "2. Go to Workflows → Import from File"
+ echo "3. Import these files:"
+ echo " - ${SCRIPT_DIR}/BotKonzept-Customer-Registration-Workflow.json"
+ echo " - ${SCRIPT_DIR}/BotKonzept-Trial-Management-Workflow.json"
+ echo ""
+ echo "4. Configure credentials:"
+ echo " - SSH (PVE20): Private key for Proxmox"
+ echo " - PostgreSQL (Supabase): Host=${SUPABASE_HOST}, DB=${SUPABASE_DB}"
+ echo " - SMTP (Postfix/SES): Your email server"
+ echo ""
+
+ read -p "Press Enter when workflows are imported and configured..."
+
+ print_success "n8n workflows configured"
+ echo ""
+}
+
+# Setup website
+setup_website() {
+ print_header "Setting up Website"
+
+ if [[ ! -d "${SCRIPT_DIR}/botkonzept-website" ]]; then
+ print_error "Website directory not found: ${SCRIPT_DIR}/botkonzept-website"
+ exit 1
+ fi
+
+ print_info "Website files location: ${SCRIPT_DIR}/botkonzept-website"
+ print_info "Target directory: ${WEBSITE_DIR}"
+ echo ""
+
+ # Update webhook URL in JavaScript
+ print_info "Updating webhook URL in JavaScript..."
+ local webhook_url="https://${N8N_HOST}/webhook/botkonzept-registration"
+
+ if [[ -f "${SCRIPT_DIR}/botkonzept-website/js/main.js" ]]; then
+ sed -i.bak "s|WEBHOOK_URL:.*|WEBHOOK_URL: '${webhook_url}',|" "${SCRIPT_DIR}/botkonzept-website/js/main.js"
+ print_success "Webhook URL updated to: ${webhook_url}"
+ fi
+
+ echo ""
+ print_info "To deploy the website, run:"
+ echo " sudo mkdir -p ${WEBSITE_DIR}"
+ echo " sudo cp -r ${SCRIPT_DIR}/botkonzept-website/* ${WEBSITE_DIR}/"
+ echo " sudo chown -R www-data:www-data ${WEBSITE_DIR}"
+ echo ""
+
+ read -p "Deploy website now? (y/N): " deploy
+ if [[ "$deploy" =~ ^[Yy]$ ]]; then
+ sudo mkdir -p "${WEBSITE_DIR}"
+ sudo cp -r "${SCRIPT_DIR}/botkonzept-website/"* "${WEBSITE_DIR}/"
+ sudo chown -R www-data:www-data "${WEBSITE_DIR}"
+ print_success "Website deployed to ${WEBSITE_DIR}"
+ else
+ print_info "Skipping website deployment"
+ fi
+
+ echo ""
+}
+
+# Test setup
+test_setup() {
+ print_header "Testing Setup"
+
+ # Test database
+ print_info "Testing database connection..."
+ if PGPASSWORD="$SUPABASE_PASSWORD" psql -h "$SUPABASE_HOST" -p "$SUPABASE_PORT" -U "$SUPABASE_USER" -d "$SUPABASE_DB" -c "SELECT COUNT(*) FROM customers" >/dev/null 2>&1; then
+ print_success "Database accessible"
+ else
+ print_error "Database not accessible"
+ fi
+
+ # Test n8n webhook
+ print_info "Testing n8n webhook..."
+ local webhook_url="https://${N8N_HOST}/webhook/botkonzept-registration"
+ local response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$webhook_url" \
+ -H "Content-Type: application/json" \
+ -d '{"test": true}' 2>/dev/null || echo "000")
+
+ if [[ "$response" == "200" ]] || [[ "$response" == "400" ]]; then
+ print_success "n8n webhook accessible (HTTP $response)"
+ else
+ print_warning "n8n webhook returned HTTP $response"
+ fi
+
+ # Test website
+ if [[ -d "$WEBSITE_DIR" ]]; then
+ print_success "Website directory exists"
+ else
+ print_warning "Website not deployed yet"
+ fi
+
+ echo ""
+}
+
+# Generate summary
+generate_summary() {
+ print_header "Setup Summary"
+
+ echo -e "${GREEN}✓ BotKonzept setup completed!${NC}"
+ echo ""
+ echo "Next steps:"
+ echo ""
+ echo "1. Configure DNS:"
+ echo " - Point botkonzept.de to your web server"
+ echo " - Configure SSL certificate (Let's Encrypt)"
+ echo ""
+ echo "2. Test registration:"
+ echo " - Visit https://botkonzept.de"
+ echo " - Fill out registration form"
+ echo " - Check email for welcome message"
+ echo ""
+ echo "3. Monitor workflows:"
+ echo " - n8n: https://${N8N_HOST}"
+ echo " - Check executions for errors"
+ echo ""
+ echo "4. Database access:"
+ echo " - Host: ${SUPABASE_HOST}"
+ echo " - Database: ${SUPABASE_DB}"
+ echo " - User: ${SUPABASE_USER}"
+ echo ""
+ echo "5. Useful queries:"
+ echo " - View customers: SELECT * FROM customer_overview;"
+ echo " - View trials: SELECT * FROM trials_expiring_soon;"
+ echo " - View emails: SELECT * FROM emails_sent ORDER BY sent_at DESC LIMIT 10;"
+ echo ""
+ echo "Documentation: ${SCRIPT_DIR}/BOTKONZEPT_README.md"
+ echo ""
+}
+
+# Main execution
+main() {
+ clear
+ print_header "BotKonzept Setup"
+
+ echo "This script will set up the complete BotKonzept platform."
+ echo ""
+ echo "Components:"
+ echo " - PostgreSQL database schema"
+ echo " - n8n workflows (manual import)"
+ echo " - Website files"
+ echo ""
+
+ read -p "Continue? (y/N): " confirm
+ if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
+ echo "Setup cancelled."
+ exit 0
+ fi
+
+ echo ""
+
+ check_prerequisites
+ setup_database
+ setup_n8n_workflows
+ setup_website
+ test_setup
+ generate_summary
+}
+
+# Run main function
+main "$@"
diff --git a/sql/botkonzept_schema.sql b/sql/botkonzept_schema.sql
new file mode 100644
index 0000000..0330350
--- /dev/null
+++ b/sql/botkonzept_schema.sql
@@ -0,0 +1,444 @@
+-- =====================================================
+-- BotKonzept - Database Schema for Customer Management
+-- =====================================================
+-- This schema manages customers, instances, emails, and payments
+-- for the BotKonzept SaaS platform
+
+-- Enable UUID extension
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+
+-- =====================================================
+-- Table: customers
+-- =====================================================
+-- Stores customer information and trial status
+CREATE TABLE IF NOT EXISTS customers (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ email VARCHAR(255) UNIQUE NOT NULL,
+ first_name VARCHAR(100) NOT NULL,
+ last_name VARCHAR(100) NOT NULL,
+ company VARCHAR(255),
+ phone VARCHAR(50),
+
+ -- Status tracking
+ status VARCHAR(50) DEFAULT 'trial' CHECK (status IN ('trial', 'active', 'cancelled', 'suspended', 'deleted')),
+
+ -- Timestamps
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ trial_end_date TIMESTAMPTZ,
+ subscription_start_date TIMESTAMPTZ,
+ subscription_end_date TIMESTAMPTZ,
+
+ -- Marketing tracking
+ utm_source VARCHAR(100),
+ utm_medium VARCHAR(100),
+ utm_campaign VARCHAR(100),
+ referral_code VARCHAR(50),
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb,
+
+ -- Indexes
+ CONSTRAINT email_format CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
+);
+
+-- Create indexes for customers
+CREATE INDEX idx_customers_email ON customers(email);
+CREATE INDEX idx_customers_status ON customers(status);
+CREATE INDEX idx_customers_created_at ON customers(created_at);
+CREATE INDEX idx_customers_trial_end_date ON customers(trial_end_date);
+
+-- =====================================================
+-- Table: instances
+-- =====================================================
+-- Stores LXC instance information for each customer
+CREATE TABLE IF NOT EXISTS instances (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
+
+ -- Instance details
+ ctid BIGINT NOT NULL UNIQUE,
+ hostname VARCHAR(255) NOT NULL,
+ ip VARCHAR(50) NOT NULL,
+ fqdn VARCHAR(255) NOT NULL,
+ vlan INTEGER,
+
+ -- Status
+ status VARCHAR(50) DEFAULT 'active' CHECK (status IN ('creating', 'active', 'suspended', 'deleted', 'error')),
+
+ -- Credentials (encrypted JSON)
+ credentials JSONB NOT NULL,
+
+ -- Timestamps
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ deleted_at TIMESTAMPTZ,
+ trial_end_date TIMESTAMPTZ,
+
+ -- Resource usage
+ disk_usage_gb DECIMAL(10,2),
+ memory_usage_mb INTEGER,
+ cpu_usage_percent DECIMAL(5,2),
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb
+);
+
+-- Create indexes for instances
+CREATE INDEX idx_instances_customer_id ON instances(customer_id);
+CREATE INDEX idx_instances_ctid ON instances(ctid);
+CREATE INDEX idx_instances_status ON instances(status);
+CREATE INDEX idx_instances_hostname ON instances(hostname);
+
+-- =====================================================
+-- Table: emails_sent
+-- =====================================================
+-- Tracks all emails sent to customers
+CREATE TABLE IF NOT EXISTS emails_sent (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
+
+ -- Email details
+ email_type VARCHAR(50) NOT NULL CHECK (email_type IN (
+ 'welcome',
+ 'day3_upgrade',
+ 'day5_reminder',
+ 'day7_last_chance',
+ 'day8_goodbye',
+ 'payment_confirm',
+ 'payment_failed',
+ 'instance_created',
+ 'instance_deleted',
+ 'password_reset',
+ 'newsletter'
+ )),
+
+ subject VARCHAR(255),
+ recipient_email VARCHAR(255) NOT NULL,
+
+ -- Status
+ status VARCHAR(50) DEFAULT 'sent' CHECK (status IN ('sent', 'delivered', 'opened', 'clicked', 'bounced', 'failed')),
+
+ -- Timestamps
+ sent_at TIMESTAMPTZ DEFAULT NOW(),
+ delivered_at TIMESTAMPTZ,
+ opened_at TIMESTAMPTZ,
+ clicked_at TIMESTAMPTZ,
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb
+);
+
+-- Create indexes for emails_sent
+CREATE INDEX idx_emails_customer_id ON emails_sent(customer_id);
+CREATE INDEX idx_emails_type ON emails_sent(email_type);
+CREATE INDEX idx_emails_sent_at ON emails_sent(sent_at);
+CREATE INDEX idx_emails_status ON emails_sent(status);
+
+-- =====================================================
+-- Table: subscriptions
+-- =====================================================
+-- Stores subscription and payment information
+CREATE TABLE IF NOT EXISTS subscriptions (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
+
+ -- Plan details
+ plan_name VARCHAR(50) NOT NULL CHECK (plan_name IN ('trial', 'starter', 'business', 'enterprise')),
+ plan_price DECIMAL(10,2) NOT NULL,
+ billing_cycle VARCHAR(20) DEFAULT 'monthly' CHECK (billing_cycle IN ('monthly', 'yearly')),
+
+ -- Discount
+ discount_percent DECIMAL(5,2) DEFAULT 0,
+ discount_code VARCHAR(50),
+ discount_end_date TIMESTAMPTZ,
+
+ -- Status
+ status VARCHAR(50) DEFAULT 'active' CHECK (status IN ('active', 'cancelled', 'past_due', 'suspended')),
+
+ -- Payment provider
+ payment_provider VARCHAR(50) CHECK (payment_provider IN ('stripe', 'paypal', 'manual')),
+ payment_provider_id VARCHAR(255),
+
+ -- Timestamps
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ current_period_start TIMESTAMPTZ,
+ current_period_end TIMESTAMPTZ,
+ cancelled_at TIMESTAMPTZ,
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb
+);
+
+-- Create indexes for subscriptions
+CREATE INDEX idx_subscriptions_customer_id ON subscriptions(customer_id);
+CREATE INDEX idx_subscriptions_status ON subscriptions(status);
+CREATE INDEX idx_subscriptions_plan_name ON subscriptions(plan_name);
+
+-- =====================================================
+-- Table: payments
+-- =====================================================
+-- Stores payment transaction history
+CREATE TABLE IF NOT EXISTS payments (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
+ subscription_id UUID REFERENCES subscriptions(id) ON DELETE SET NULL,
+
+ -- Payment details
+ amount DECIMAL(10,2) NOT NULL,
+ currency VARCHAR(3) DEFAULT 'EUR',
+
+ -- Status
+ status VARCHAR(50) DEFAULT 'pending' CHECK (status IN ('pending', 'succeeded', 'failed', 'refunded', 'cancelled')),
+
+ -- Payment provider
+ payment_provider VARCHAR(50) CHECK (payment_provider IN ('stripe', 'paypal', 'manual')),
+ payment_provider_id VARCHAR(255),
+ payment_method VARCHAR(50),
+
+ -- Timestamps
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ paid_at TIMESTAMPTZ,
+ refunded_at TIMESTAMPTZ,
+
+ -- Invoice
+ invoice_number VARCHAR(50),
+ invoice_url TEXT,
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb
+);
+
+-- Create indexes for payments
+CREATE INDEX idx_payments_customer_id ON payments(customer_id);
+CREATE INDEX idx_payments_subscription_id ON payments(subscription_id);
+CREATE INDEX idx_payments_status ON payments(status);
+CREATE INDEX idx_payments_created_at ON payments(created_at);
+
+-- =====================================================
+-- Table: usage_stats
+-- =====================================================
+-- Tracks usage statistics for each instance
+CREATE TABLE IF NOT EXISTS usage_stats (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
+
+ -- Usage metrics
+ date DATE NOT NULL,
+ messages_count INTEGER DEFAULT 0,
+ documents_count INTEGER DEFAULT 0,
+ api_calls_count INTEGER DEFAULT 0,
+ storage_used_mb DECIMAL(10,2) DEFAULT 0,
+
+ -- Timestamps
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+
+ -- Unique constraint: one record per instance per day
+ UNIQUE(instance_id, date)
+);
+
+-- Create indexes for usage_stats
+CREATE INDEX idx_usage_instance_id ON usage_stats(instance_id);
+CREATE INDEX idx_usage_date ON usage_stats(date);
+
+-- =====================================================
+-- Table: audit_log
+-- =====================================================
+-- Audit trail for important actions
+CREATE TABLE IF NOT EXISTS audit_log (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ customer_id UUID REFERENCES customers(id) ON DELETE SET NULL,
+ instance_id UUID REFERENCES instances(id) ON DELETE SET NULL,
+
+ -- Action details
+ action VARCHAR(100) NOT NULL,
+ entity_type VARCHAR(50),
+ entity_id UUID,
+
+ -- User/system that performed the action
+ performed_by VARCHAR(100),
+ ip_address INET,
+ user_agent TEXT,
+
+ -- Changes
+ old_values JSONB,
+ new_values JSONB,
+
+ -- Timestamp
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+
+ -- Metadata
+ metadata JSONB DEFAULT '{}'::jsonb
+);
+
+-- Create indexes for audit_log
+CREATE INDEX idx_audit_customer_id ON audit_log(customer_id);
+CREATE INDEX idx_audit_instance_id ON audit_log(instance_id);
+CREATE INDEX idx_audit_action ON audit_log(action);
+CREATE INDEX idx_audit_created_at ON audit_log(created_at);
+
+-- =====================================================
+-- Functions & Triggers
+-- =====================================================
+
+-- Function to update updated_at timestamp
+CREATE OR REPLACE FUNCTION update_updated_at_column()
+RETURNS TRIGGER AS $$
+BEGIN
+ NEW.updated_at = NOW();
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+-- Triggers for updated_at
+CREATE TRIGGER update_customers_updated_at BEFORE UPDATE ON customers
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
+
+CREATE TRIGGER update_instances_updated_at BEFORE UPDATE ON instances
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
+
+CREATE TRIGGER update_subscriptions_updated_at BEFORE UPDATE ON subscriptions
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
+
+-- Function to calculate trial end date
+CREATE OR REPLACE FUNCTION set_trial_end_date()
+RETURNS TRIGGER AS $$
+BEGIN
+ IF NEW.trial_end_date IS NULL THEN
+ NEW.trial_end_date = NEW.created_at + INTERVAL '7 days';
+ END IF;
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+-- Trigger for trial end date
+CREATE TRIGGER set_customer_trial_end_date BEFORE INSERT ON customers
+ FOR EACH ROW EXECUTE FUNCTION set_trial_end_date();
+
+-- =====================================================
+-- Views
+-- =====================================================
+
+-- View: Active trials expiring soon
+CREATE OR REPLACE VIEW trials_expiring_soon AS
+SELECT
+ c.id,
+ c.email,
+ c.first_name,
+ c.last_name,
+ c.created_at,
+ c.trial_end_date,
+ EXTRACT(DAY FROM (c.trial_end_date - NOW())) as days_remaining,
+ i.ctid,
+ i.hostname,
+ i.fqdn
+FROM customers c
+JOIN instances i ON c.id = i.customer_id
+WHERE c.status = 'trial'
+ AND i.status = 'active'
+ AND c.trial_end_date > NOW()
+ AND c.trial_end_date <= NOW() + INTERVAL '3 days';
+
+-- View: Customer overview with instance info
+CREATE OR REPLACE VIEW customer_overview AS
+SELECT
+ c.id,
+ c.email,
+ c.first_name,
+ c.last_name,
+ c.company,
+ c.status,
+ c.created_at,
+ c.trial_end_date,
+ i.ctid,
+ i.hostname,
+ i.fqdn,
+ i.ip,
+ i.status as instance_status,
+ s.plan_name,
+ s.plan_price,
+ s.status as subscription_status
+FROM customers c
+LEFT JOIN instances i ON c.id = i.customer_id AND i.status = 'active'
+LEFT JOIN subscriptions s ON c.id = s.customer_id AND s.status = 'active';
+
+-- View: Revenue metrics
+CREATE OR REPLACE VIEW revenue_metrics AS
+SELECT
+ DATE_TRUNC('month', paid_at) as month,
+ COUNT(*) as payment_count,
+ SUM(amount) as total_revenue,
+ AVG(amount) as average_payment,
+ COUNT(DISTINCT customer_id) as unique_customers
+FROM payments
+WHERE status = 'succeeded'
+ AND paid_at IS NOT NULL
+GROUP BY DATE_TRUNC('month', paid_at)
+ORDER BY month DESC;
+
+-- =====================================================
+-- Row Level Security (RLS) Policies
+-- =====================================================
+
+-- Enable RLS on tables
+ALTER TABLE customers ENABLE ROW LEVEL SECURITY;
+ALTER TABLE instances ENABLE ROW LEVEL SECURITY;
+ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
+ALTER TABLE payments ENABLE ROW LEVEL SECURITY;
+
+-- Policy: Customers can only see their own data
+CREATE POLICY customers_select_own ON customers
+ FOR SELECT
+ USING (auth.uid()::text = id::text);
+
+CREATE POLICY instances_select_own ON instances
+ FOR SELECT
+ USING (customer_id::text = auth.uid()::text);
+
+CREATE POLICY subscriptions_select_own ON subscriptions
+ FOR SELECT
+ USING (customer_id::text = auth.uid()::text);
+
+CREATE POLICY payments_select_own ON payments
+ FOR SELECT
+ USING (customer_id::text = auth.uid()::text);
+
+-- =====================================================
+-- Sample Data (for testing)
+-- =====================================================
+
+-- Insert sample customer (commented out for production)
+-- INSERT INTO customers (email, first_name, last_name, company, status)
+-- VALUES ('test@example.com', 'Max', 'Mustermann', 'Test GmbH', 'trial');
+
+-- =====================================================
+-- Grants
+-- =====================================================
+
+-- Grant permissions to authenticated users
+GRANT SELECT, INSERT, UPDATE ON customers TO authenticated;
+GRANT SELECT ON instances TO authenticated;
+GRANT SELECT ON subscriptions TO authenticated;
+GRANT SELECT ON payments TO authenticated;
+GRANT SELECT ON usage_stats TO authenticated;
+
+-- Grant all permissions to service role (for n8n workflows)
+GRANT ALL ON ALL TABLES IN SCHEMA public TO service_role;
+GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO service_role;
+
+-- =====================================================
+-- Comments
+-- =====================================================
+
+COMMENT ON TABLE customers IS 'Stores customer information and trial status';
+COMMENT ON TABLE instances IS 'Stores LXC instance information for each customer';
+COMMENT ON TABLE emails_sent IS 'Tracks all emails sent to customers';
+COMMENT ON TABLE subscriptions IS 'Stores subscription and payment information';
+COMMENT ON TABLE payments IS 'Stores payment transaction history';
+COMMENT ON TABLE usage_stats IS 'Tracks usage statistics for each instance';
+COMMENT ON TABLE audit_log IS 'Audit trail for important actions';
+
+-- =====================================================
+-- End of Schema
+-- =====================================================