From f881f668a6b14174b5ba9a62e64a904f9d0b4886 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Wed, 1 Oct 2025 09:52:59 +0000 Subject: [PATCH] Add Docker support and installation guide for easy server deployment Includes a Dockerfile for building the application image and an INSTALLATION.md file detailing the setup process, prerequisites, and helpful commands for managing the application on a private server. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/ds3R7vP --- .dockerignore | 40 + .env.example | 29 + .gitignore | 6 + .replit | 46 + Dockerfile | 44 + INSTALLATION.md | 161 + client/index.html | 14 + client/src/App.tsx | 31 + client/src/components/ai-chat.tsx | 192 + client/src/components/calendar-view.tsx | 178 + client/src/components/managed-pages.tsx | 83 + client/src/components/media-upload.tsx | 229 + client/src/components/quick-actions.tsx | 115 + client/src/components/sidebar.tsx | 112 + client/src/components/stats-cards.tsx | 100 + client/src/components/topbar.tsx | 42 + client/src/components/ui/accordion.tsx | 56 + client/src/components/ui/alert-dialog.tsx | 139 + client/src/components/ui/alert.tsx | 59 + client/src/components/ui/aspect-ratio.tsx | 5 + client/src/components/ui/avatar.tsx | 50 + client/src/components/ui/badge.tsx | 36 + client/src/components/ui/breadcrumb.tsx | 115 + client/src/components/ui/button.tsx | 56 + client/src/components/ui/calendar.tsx | 68 + client/src/components/ui/card.tsx | 79 + client/src/components/ui/carousel.tsx | 260 + client/src/components/ui/chart.tsx | 365 + client/src/components/ui/checkbox.tsx | 28 + client/src/components/ui/collapsible.tsx | 11 + client/src/components/ui/command.tsx | 151 + client/src/components/ui/context-menu.tsx | 198 + client/src/components/ui/dialog.tsx | 122 + client/src/components/ui/drawer.tsx | 118 + client/src/components/ui/dropdown-menu.tsx | 198 + client/src/components/ui/form.tsx | 178 + client/src/components/ui/hover-card.tsx | 29 + client/src/components/ui/input-otp.tsx | 69 + client/src/components/ui/input.tsx | 22 + client/src/components/ui/label.tsx | 24 + client/src/components/ui/menubar.tsx | 256 + client/src/components/ui/navigation-menu.tsx | 128 + client/src/components/ui/pagination.tsx | 117 + client/src/components/ui/popover.tsx | 29 + client/src/components/ui/progress.tsx | 28 + client/src/components/ui/radio-group.tsx | 42 + client/src/components/ui/resizable.tsx | 45 + client/src/components/ui/scroll-area.tsx | 46 + client/src/components/ui/select.tsx | 160 + client/src/components/ui/separator.tsx | 29 + client/src/components/ui/sheet.tsx | 140 + client/src/components/ui/sidebar.tsx | 771 ++ client/src/components/ui/skeleton.tsx | 15 + client/src/components/ui/slider.tsx | 26 + client/src/components/ui/switch.tsx | 27 + client/src/components/ui/table.tsx | 117 + client/src/components/ui/tabs.tsx | 53 + client/src/components/ui/textarea.tsx | 22 + client/src/components/ui/toast.tsx | 127 + client/src/components/ui/toaster.tsx | 33 + client/src/components/ui/toggle-group.tsx | 61 + client/src/components/ui/toggle.tsx | 43 + client/src/components/ui/tooltip.tsx | 30 + client/src/hooks/use-mobile.tsx | 19 + client/src/hooks/use-toast.ts | 191 + client/src/index.css | 144 + client/src/lib/queryClient.ts | 57 + client/src/lib/utils.ts | 6 + client/src/main.tsx | 5 + client/src/pages/dashboard.tsx | 64 + client/src/pages/not-found.tsx | 21 + components.json | 20 + docker-compose.yml | 48 + drizzle.config.ts | 14 + package-lock.json | 8915 ++++++++++++++++++ package.json | 112 + postcss.config.js | 6 + server/db.ts | 15 + server/index.ts | 85 + server/routes.ts | 201 + server/services/imageProcessor.ts | 102 + server/services/openrouter.ts | 148 + server/services/scheduler.ts | 69 + server/storage.ts | 213 + server/vite.ts | 85 + shared/schema.ts | 194 + tailwind.config.ts | 95 + tsconfig.json | 23 + vite.config.ts | 40 + 89 files changed, 17095 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 .replit create mode 100644 Dockerfile create mode 100644 INSTALLATION.md create mode 100644 client/index.html create mode 100644 client/src/App.tsx create mode 100644 client/src/components/ai-chat.tsx create mode 100644 client/src/components/calendar-view.tsx create mode 100644 client/src/components/managed-pages.tsx create mode 100644 client/src/components/media-upload.tsx create mode 100644 client/src/components/quick-actions.tsx create mode 100644 client/src/components/sidebar.tsx create mode 100644 client/src/components/stats-cards.tsx create mode 100644 client/src/components/topbar.tsx create mode 100644 client/src/components/ui/accordion.tsx create mode 100644 client/src/components/ui/alert-dialog.tsx create mode 100644 client/src/components/ui/alert.tsx create mode 100644 client/src/components/ui/aspect-ratio.tsx create mode 100644 client/src/components/ui/avatar.tsx create mode 100644 client/src/components/ui/badge.tsx create mode 100644 client/src/components/ui/breadcrumb.tsx create mode 100644 client/src/components/ui/button.tsx create mode 100644 client/src/components/ui/calendar.tsx create mode 100644 client/src/components/ui/card.tsx create mode 100644 client/src/components/ui/carousel.tsx create mode 100644 client/src/components/ui/chart.tsx create mode 100644 client/src/components/ui/checkbox.tsx create mode 100644 client/src/components/ui/collapsible.tsx create mode 100644 client/src/components/ui/command.tsx create mode 100644 client/src/components/ui/context-menu.tsx create mode 100644 client/src/components/ui/dialog.tsx create mode 100644 client/src/components/ui/drawer.tsx create mode 100644 client/src/components/ui/dropdown-menu.tsx create mode 100644 client/src/components/ui/form.tsx create mode 100644 client/src/components/ui/hover-card.tsx create mode 100644 client/src/components/ui/input-otp.tsx create mode 100644 client/src/components/ui/input.tsx create mode 100644 client/src/components/ui/label.tsx create mode 100644 client/src/components/ui/menubar.tsx create mode 100644 client/src/components/ui/navigation-menu.tsx create mode 100644 client/src/components/ui/pagination.tsx create mode 100644 client/src/components/ui/popover.tsx create mode 100644 client/src/components/ui/progress.tsx create mode 100644 client/src/components/ui/radio-group.tsx create mode 100644 client/src/components/ui/resizable.tsx create mode 100644 client/src/components/ui/scroll-area.tsx create mode 100644 client/src/components/ui/select.tsx create mode 100644 client/src/components/ui/separator.tsx create mode 100644 client/src/components/ui/sheet.tsx create mode 100644 client/src/components/ui/sidebar.tsx create mode 100644 client/src/components/ui/skeleton.tsx create mode 100644 client/src/components/ui/slider.tsx create mode 100644 client/src/components/ui/switch.tsx create mode 100644 client/src/components/ui/table.tsx create mode 100644 client/src/components/ui/tabs.tsx create mode 100644 client/src/components/ui/textarea.tsx create mode 100644 client/src/components/ui/toast.tsx create mode 100644 client/src/components/ui/toaster.tsx create mode 100644 client/src/components/ui/toggle-group.tsx create mode 100644 client/src/components/ui/toggle.tsx create mode 100644 client/src/components/ui/tooltip.tsx create mode 100644 client/src/hooks/use-mobile.tsx create mode 100644 client/src/hooks/use-toast.ts create mode 100644 client/src/index.css create mode 100644 client/src/lib/queryClient.ts create mode 100644 client/src/lib/utils.ts create mode 100644 client/src/main.tsx create mode 100644 client/src/pages/dashboard.tsx create mode 100644 client/src/pages/not-found.tsx create mode 100644 components.json create mode 100644 docker-compose.yml create mode 100644 drizzle.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 server/db.ts create mode 100644 server/index.ts create mode 100644 server/routes.ts create mode 100644 server/services/imageProcessor.ts create mode 100644 server/services/openrouter.ts create mode 100644 server/services/scheduler.ts create mode 100644 server/storage.ts create mode 100644 server/vite.ts create mode 100644 shared/schema.ts create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8c6cc6c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +# Dépendances +node_modules +npm-debug.log + +# Fichiers de build +dist +.vite + +# Fichiers de développement +.env +.env.local +.env.*.local + +# Fichiers Git +.git +.gitignore + +# Fichiers Replit +.replit +replit.nix + +# Fichiers de test +*.test.js +*.test.ts +__tests__ + +# Documentation +*.md +!README.md + +# Fichiers système +.DS_Store +Thumbs.db + +# Logs +logs +*.log + +# Uploads (seront montés comme volume) +uploads/* diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5cf910a --- /dev/null +++ b/.env.example @@ -0,0 +1,29 @@ +# Configuration de la base de données PostgreSQL +PGDATABASE=socialflow +PGUSER=socialflow +PGPASSWORD=changeme +PGPORT=5432 +PGHOST=postgres + +# URL de connexion complète (générée automatiquement dans Docker) +DATABASE_URL=postgresql://socialflow:changeme@postgres:5432/socialflow + +# Configuration de l'application +PORT=5000 +NODE_ENV=production +APP_URL=http://localhost:5000 + +# Clé secrète pour les sessions (CHANGEZ CETTE VALEUR) +SESSION_SECRET=your-secret-key-change-me-to-random-string + +# Clé API OpenRouter pour la génération de texte IA +# Obtenez votre clé sur https://openrouter.ai/ +OPENROUTER_API_KEY=your-openrouter-api-key-here + +# Optionnel: Configuration Facebook API +# FACEBOOK_APP_ID= +# FACEBOOK_APP_SECRET= + +# Optionnel: Configuration Instagram API +# INSTAGRAM_APP_ID= +# INSTAGRAM_APP_SECRET= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f9ba7f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +dist +.DS_Store +server/public +vite.config.ts.* +*.tar.gz \ No newline at end of file diff --git a/.replit b/.replit new file mode 100644 index 0000000..3cb59c7 --- /dev/null +++ b/.replit @@ -0,0 +1,46 @@ +modules = ["nodejs-20", "web", "postgresql-16"] +run = "npm run dev" +hidden = [".config", ".git", "generated-icon.png", "node_modules", "dist"] + +[nix] +channel = "stable-24_05" + +[deployment] +deploymentTarget = "autoscale" +build = ["npm", "run", "build"] +run = ["npm", "run", "start"] + +[[ports]] +localPort = 5000 +externalPort = 80 + +[[ports]] +localPort = 32809 +externalPort = 3000 + +[env] +PORT = "5000" + +[agent] +integrations = ["javascript_object_storage:1.0.0", "javascript_database:1.0.0"] + +[workflows] +runButton = "Project" + +[[workflows.workflow]] +name = "Project" +mode = "parallel" +author = "agent" + +[[workflows.workflow.tasks]] +task = "workflow.run" +args = "Start application" + +[[workflows.workflow]] +name = "Start application" +author = "agent" + +[[workflows.workflow.tasks]] +task = "shell.exec" +args = "npm run dev" +waitForPort = 5000 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..169acce --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +# Étape 1: Build de l'application +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copier les fichiers de dépendances +COPY package*.json ./ + +# Installer toutes les dépendances (dev + prod) +RUN npm ci + +# Copier le reste du code source +COPY . . + +# Build du frontend +RUN npm run build + +# Étape 2: Image de production +FROM node:20-alpine + +WORKDIR /app + +# Installer uniquement les dépendances de production +COPY package*.json ./ +RUN npm ci --only=production + +# Copier les fichiers buildés et le code serveur +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/server ./server +COPY --from=builder /app/shared ./shared +COPY --from=builder /app/drizzle.config.ts ./ + +# Créer le dossier uploads +RUN mkdir -p uploads + +# Exposer le port 5000 +EXPOSE 5000 + +# Variables d'environnement par défaut +ENV NODE_ENV=production +ENV PORT=5000 + +# Démarrer l'application +CMD ["node", "dist/server.js"] diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 0000000..24ee8e2 --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,161 @@ +# Installation de Social Flow sur un serveur privé + +## Prérequis + +- Docker et Docker Compose installés sur votre serveur +- Clé API OpenRouter (https://openrouter.ai/) +- (Optionnel) Tokens d'accès Facebook et Instagram + +## Installation rapide + +### 1. Cloner ou télécharger l'application + +```bash +git clone socialflow +cd socialflow +``` + +### 2. Configurer les variables d'environnement + +Copiez le fichier d'exemple et modifiez les valeurs : + +```bash +cp .env.example .env +nano .env # ou utilisez votre éditeur préféré +``` + +**Variables importantes à modifier :** + +- `PGPASSWORD` : Changez le mot de passe de la base de données +- `SESSION_SECRET` : Générez une clé secrète aléatoire +- `OPENROUTER_API_KEY` : Votre clé API OpenRouter +- `APP_URL` : L'URL publique de votre application + +### 3. Démarrer l'application + +```bash +docker-compose up -d +``` + +L'application sera accessible sur `http://localhost:5000` (ou le port configuré). + +### 4. Vérifier le statut + +```bash +# Voir les logs +docker-compose logs -f app + +# Vérifier que les containers sont démarrés +docker-compose ps +``` + +## Commandes utiles + +### Arrêter l'application +```bash +docker-compose down +``` + +### Redémarrer l'application +```bash +docker-compose restart +``` + +### Voir les logs +```bash +# Logs de l'application +docker-compose logs -f app + +# Logs de la base de données +docker-compose logs -f postgres +``` + +### Mettre à jour l'application +```bash +# Arrêter l'application +docker-compose down + +# Récupérer les dernières modifications +git pull + +# Reconstruire et redémarrer +docker-compose up -d --build +``` + +### Sauvegarder la base de données +```bash +docker exec socialflow-db pg_dump -U socialflow socialflow > backup.sql +``` + +### Restaurer la base de données +```bash +docker exec -i socialflow-db psql -U socialflow socialflow < backup.sql +``` + +## Configuration avancée + +### Changer le port d'exposition + +Modifiez le fichier `docker-compose.yml` : + +```yaml +services: + app: + ports: + - "8080:5000" # Exposer sur le port 8080 +``` + +### Utiliser un domaine personnalisé + +1. Configurez votre reverse proxy (Nginx, Caddy, etc.) +2. Pointez vers `http://localhost:5000` +3. Mettez à jour `APP_URL` dans `.env` + +### Exemple de configuration Nginx + +```nginx +server { + listen 80; + server_name socialflow.votredomaine.com; + + location / { + proxy_pass http://localhost:5000; + 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; + } +} +``` + +## Résolution de problèmes + +### L'application ne démarre pas + +1. Vérifiez les logs : `docker-compose logs -f` +2. Assurez-vous que les ports ne sont pas déjà utilisés +3. Vérifiez que Docker a suffisamment de ressources + +### Erreurs de base de données + +1. Vérifiez que PostgreSQL est démarré : `docker-compose ps` +2. Vérifiez les credentials dans `.env` +3. Recréez la base si nécessaire : `docker-compose down -v && docker-compose up -d` + +### Problèmes de performance + +1. Augmentez les ressources Docker +2. Configurez un reverse proxy avec cache +3. Utilisez un stockage SSD pour les volumes + +## Sécurité + +- Changez toujours `PGPASSWORD` et `SESSION_SECRET` +- Utilisez HTTPS en production (avec Let's Encrypt par exemple) +- Configurez un firewall pour limiter l'accès aux ports +- Mettez à jour régulièrement les images Docker + +## Support + +Pour plus d'informations ou en cas de problème, consultez la documentation ou ouvrez une issue. diff --git a/client/index.html b/client/index.html new file mode 100644 index 0000000..f15fa88 --- /dev/null +++ b/client/index.html @@ -0,0 +1,14 @@ + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 0000000..40f7f31 --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,31 @@ +import { Switch, Route } from "wouter"; +import { queryClient } from "./lib/queryClient"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { Toaster } from "@/components/ui/toaster"; +import { TooltipProvider } from "@/components/ui/tooltip"; +import NotFound from "@/pages/not-found"; +import Dashboard from "@/pages/dashboard"; + +function Router() { + return ( + + + + + ); +} + +function App() { + return ( + + +
+ + +
+
+
+ ); +} + +export default App; diff --git a/client/src/components/ai-chat.tsx b/client/src/components/ai-chat.tsx new file mode 100644 index 0000000..48427de --- /dev/null +++ b/client/src/components/ai-chat.tsx @@ -0,0 +1,192 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { useMutation, useQuery } from "@tanstack/react-query"; +import { apiRequest, queryClient } from "@/lib/queryClient"; +import { Bot, User, Lightbulb, History, Zap } from "lucide-react"; +import { useToast } from "@/hooks/use-toast"; + +interface Message { + role: "user" | "assistant"; + content: string; + variants?: Array<{ variant: string; text: string; characterCount: number }>; +} + +export default function AiChat() { + const [messages, setMessages] = useState([ + { + role: "assistant", + content: "Bonjour ! Je suis votre assistant IA. Fournissez-moi les informations sur votre produit (nom, description, caractéristiques, prix) et je générerai automatiquement du contenu optimisé pour vos publications Facebook et Instagram.", + }, + ]); + const [input, setInput] = useState(""); + const { toast } = useToast(); + + const generateMutation = useMutation({ + mutationFn: async (productInfo: any) => { + const response = await apiRequest("POST", "/api/ai/generate", productInfo); + return response.json(); + }, + onSuccess: (data) => { + setMessages((prev) => [ + ...prev, + { + role: "assistant", + content: "Parfait ! J'ai généré 3 variantes de texte pour votre produit. Choisissez celle qui vous convient :", + variants: data.variants, + }, + ]); + queryClient.invalidateQueries({ queryKey: ["/api/ai/generations"] }); + }, + onError: () => { + toast({ + title: "Erreur", + description: "Impossible de générer le texte. Vérifiez votre clé API OpenRouter.", + variant: "destructive", + }); + }, + }); + + const handleSubmit = () => { + if (!input.trim()) return; + + // Add user message + const userMessage = input; + setMessages((prev) => [...prev, { role: "user", content: userMessage }]); + + // Parse product info from input (simple parsing) + const productInfo = { + name: userMessage.match(/Produit:\s*(.+?)(?:\n|$)/i)?.[1] || userMessage, + price: userMessage.match(/Prix:\s*(.+?)(?:\n|$)/i)?.[1] || "", + description: userMessage.match(/Description:\s*(.+?)(?:\n|$)/i)?.[1] || "", + features: userMessage.match(/Caractéristiques:\s*(.+?)(?:\n|$)/i)?.[1]?.split(",") || [], + }; + + generateMutation.mutate(productInfo); + setInput(""); + }; + + return ( +
+
+
+
+ +
+
+

Assistant IA - Génération de contenu

+

Décrivez votre produit pour générer du texte

+
+
+ +
+ +
+ {messages.map((message, index) => ( +
+ {message.role === "assistant" && ( +
+ +
+ )} + +
+
+

{message.content}

+ + {message.variants && ( +
+ {message.variants.map((variant, vIndex) => ( +
+
+ + {variant.variant} + + {variant.characterCount} caractères +
+

{variant.text}

+
+ ))} +
+ )} +
+ + {message.role === "user" ? "Maintenant" : "Il y a quelques secondes"} + +
+ + {message.role === "user" && ( +
+ +
+ )} +
+ ))} +
+ +
+
+