From 45ca9a31220141a8fa64808acb8fdb66d2c5ed2c Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 2 Oct 2025 16:56:47 +0000 Subject: [PATCH 1/9] Add automated posting to Facebook and Instagram No changes were made to the repository. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/Ob3gzfQ --- .replit | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.replit b/.replit index 0556bf9..ad64fe1 100644 --- a/.replit +++ b/.replit @@ -14,10 +14,6 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 -[[ports]] -localPort = 35981 -externalPort = 3002 - [[ports]] localPort = 40537 externalPort = 3000 From bec082180ba27517c278148481db2c310903eef5 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 2 Oct 2025 17:03:51 +0000 Subject: [PATCH 2/9] Update Facebook API call to correctly schedule posts Modifies the `published` parameter in the FacebookService from 'false' to '0' for scheduled posts. Includes a new n8n workflow JSON file for asset management. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/Ob3gzfQ --- .../My workflow 8 (1)_1759424373567.json | 322 ++++++++++++++++++ server/services/facebook.ts | 4 +- 2 files changed, 324 insertions(+), 2 deletions(-) create mode 100644 attached_assets/My workflow 8 (1)_1759424373567.json diff --git a/attached_assets/My workflow 8 (1)_1759424373567.json b/attached_assets/My workflow 8 (1)_1759424373567.json new file mode 100644 index 0000000..286544f --- /dev/null +++ b/attached_assets/My workflow 8 (1)_1759424373567.json @@ -0,0 +1,322 @@ +{ + "name": "My workflow 8", + "nodes": [ + { + "parameters": { + "formTitle": "SocialFlow", + "formFields": { + "values": [ + { + "fieldLabel": "Non du produit", + "placeholder": "nom_produit", + "requiredField": true + }, + { + "fieldLabel": "Prix", + "placeholder": "prix", + "requiredField": true + }, + { + "fieldLabel": "Caractéristiques", + "placeholder": "caractéristiques" + }, + { + "fieldLabel": "Promo", + "placeholder": "promo" + }, + { + "fieldLabel": "Date publication", + "fieldType": "date", + "requiredField": true + }, + { + "fieldLabel": "Heure de publication (HH:mm)", + "placeholder": "heure_publication", + "requiredField": true + }, + { + "fieldLabel": "Photo", + "fieldType": "file", + "acceptFileTypes": "photo" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.formTrigger", + "typeVersion": 2.2, + "position": [ + -720, + 160 + ], + "id": "3441e9d7-35ff-4f14-bee8-78397d0e2e28", + "name": "On form submission", + "webhookId": "17357858-667e-4a3d-afd1-82039f41c927" + }, + { + "parameters": { + "method": "POST", + "url": "=https://api.cloudinary.com/v1_1/dspr8yjfu/image/upload", + "sendBody": true, + "contentType": "multipart-form-data", + "bodyParameters": { + "parameters": [ + { + "name": "upload_preset", + "value": "=upload_n8n" + }, + { + "parameterType": "formBinaryData", + "name": "file", + "inputDataFieldName": "Photo" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + -208, + 16 + ], + "id": "49ff16a6-a004-4ff4-a1dc-cb6902f7f46a", + "name": "HTTP Request" + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "14257b6b-82c8-4151-85a5-f56ab814f6f3", + "name": "image_ready_url", + "value": "={{$json.secure_url\n ? $json.secure_url.replace('/upload/','/upload/c_fill,g_auto,h_1350,w_1080,q_auto,f_auto,e_auto_contrast,e_auto_color,e_sharpen:50/')\n : ''}}\n", + "type": "string" + }, + { + "id": "74f9dbae-0e18-4cdb-b316-5976f65ad6c8", + "name": "image_public_id", + "value": "={{$json.public_id}}", + "type": "string" + } + ] + }, + "includeOtherFields": true, + "options": {} + }, + "type": "n8n-nodes-base.set", + "typeVersion": 3.4, + "position": [ + 16, + 16 + ], + "id": "dc95401f-403a-4a72-87e6-622709b10046", + "name": "Edit Fields" + }, + { + "parameters": { + "promptType": "define", + "text": "=Langue: fr\nPAS DE TEXTE AVANT OU APRÈS.\n\nContraintes:\n- Accroche d'ouverture engageante\n- 1-2 phrases sur bénéfice client, pas style catalogue\n- Pas de lien, pas d'URL\n- 3-5 hashtags ciblés (locaux/thématiques) Ajouter #lafoirfouille\n- Ton chaleureux, concret, non agressif\n- Maximum 250 caractères \n\nContexte:\n- Produit: {{ $('On form submission').item.json['Non du produit'] }}\n- Prix: {{ $('On form submission').item.json.Prix }}\n- Caractéristiques: {{ $('On form submission').item.json['Caractéristiques'] }}\n- Promo: {{$json.promo || \"aucune\"}}\n", + "messages": { + "messageValues": [ + { + "message": "Tu es un community manager de boutique physique. Tu écris pour Facebook. Objectif: engagement + visites en magasin. Pas de lien web. pas de json que du texte pure avec quelques emoji. structure le texte pour un post facebook et instagram - ne parle pas de boutique locale." + } + ] + }, + "batching": {} + }, + "type": "@n8n/n8n-nodes-langchain.chainLlm", + "typeVersion": 1.7, + "position": [ + 240, + 16 + ], + "id": "b7de85b4-8a06-4cd6-b3b1-dd28f7e30720", + "name": "Basic LLM Chain", + "alwaysOutputData": true + }, + { + "parameters": { + "model": "openai/gpt-4o", + "options": {} + }, + "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter", + "typeVersion": 1, + "position": [ + 224, + 320 + ], + "id": "03c7dc91-a5e0-4b58-946f-7217cfbb7f22", + "name": "OpenRouter Chat Model", + "credentials": { + "openRouterApi": { + "id": "QrDzqP7MluNzhC1L", + "name": "OpenRouter account" + } + } + }, + { + "parameters": { + "method": "POST", + "url": "=https://graph.facebook.com/v23.0/119315771483782/photos", + "sendQuery": true, + "queryParameters": { + "parameters": [ + { + "name": "url", + "value": "={{ $('Edit Fields').first().json.image_ready_url.trim().replace(/\\)+$/,'') }}\n" + }, + { + "name": "message", + "value": "={{ $json.text }}" + }, + { + "name": "access_token", + "value": "EAASQALmsF1UBPlhtfZBbZCkuu9fZAbr8OpEAXuXcLuZCAx6F2BmhZBprak0AQfdqKZA0aGsR8pDtpqmkBjb7lIqZCadMJ919IrvwwE75nEo1uZCIIuAJDqkq3Cl9feQMX126sPIabGerrLtd8Dw5NGlQTNzYB7KYqUgcjZA6N5fDt7Bn4pMKMzsh0p5MCxMxq5xV1qyNLVykNMbgE7HZBkas1oLdeFj3M2hAZAYlS4NBuoZD" + }, + { + "name": "published", + "value": "=0" + }, + { + "name": "scheduled_publish_time", + "value": "={{ $json.scheduled_publish_time }}" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1040, + -16 + ], + "id": "6fbaf6c3-1744-4116-b599-047a978ba504", + "name": "Facebook Post Photo" + }, + { + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "// Récupère les valeurs depuis le Form Trigger, pas depuis l'item courant\nconst dateStr = $item(0).$node[\"On form submission\"].json[\"Date publication\"];\nconst timeStr = $item(0).$node[\"On form submission\"].json[\"Heure de publication (HH:mm)\"];\n\nif (!dateStr || !timeStr) {\n throw new Error(\"Champs manquants: \" + JSON.stringify({ dateStr, timeStr }));\n}\n\nconst [y,m,d] = dateStr.split('-').map(Number);\nconst [H,Mi] = timeStr.split(':').map(Number);\n\n// Epoch UTC\nlet ts = Math.floor(Date.UTC(y, m - 1, d, H, Mi) / 1000);\n\n// Sécurité: forcer ≥ maintenant+600s\nconst now = Math.floor(Date.now()/1000);\nif (ts < now + 600) ts = now + 1200;\n\nreturn { json: { ...$json, scheduled_publish_time: ts } };\n" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 816, + 144 + ], + "id": "93f14550-2ccd-4da7-bfb7-7ecacee3e830", + "name": "Code", + "alwaysOutputData": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 592, + 144 + ], + "id": "557d9b2a-ceb1-42d8-ad2d-29e8c2533d51", + "name": "Merge" + } + ], + "pinData": {}, + "connections": { + "On form submission": { + "main": [ + [ + { + "node": "HTTP Request", + "type": "main", + "index": 0 + }, + { + "node": "Merge", + "type": "main", + "index": 1 + } + ] + ] + }, + "HTTP Request": { + "main": [ + [ + { + "node": "Edit Fields", + "type": "main", + "index": 0 + } + ] + ] + }, + "OpenRouter Chat Model": { + "ai_languageModel": [ + [ + { + "node": "Basic LLM Chain", + "type": "ai_languageModel", + "index": 0 + } + ] + ] + }, + "Edit Fields": { + "main": [ + [ + { + "node": "Basic LLM Chain", + "type": "main", + "index": 0 + } + ] + ] + }, + "Basic LLM Chain": { + "main": [ + [ + { + "node": "Merge", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "Facebook Post Photo", + "type": "main", + "index": 0 + } + ] + ] + }, + "Merge": { + "main": [ + [ + { + "node": "Code", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "72a43b73-4460-49de-88aa-90afde0ef73b", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "95265e6405e55fa03a3687565ed8e8c464bd659d0d56a9696d7d25f954abf511" + }, + "id": "cTnh6OMO9wxPEPBS", + "tags": [] +} \ No newline at end of file diff --git a/server/services/facebook.ts b/server/services/facebook.ts index 41e1d54..bacf4e2 100644 --- a/server/services/facebook.ts +++ b/server/services/facebook.ts @@ -121,7 +121,7 @@ export class FacebookService { const params = new URLSearchParams({ access_token: page.accessToken!, message: post.content, - published: 'false', + published: '0', scheduled_publish_time: scheduledTimestamp.toString(), }); @@ -147,7 +147,7 @@ export class FacebookService { access_token: page.accessToken!, message: post.content, url: photoUrl, - published: 'false', + published: '0', scheduled_publish_time: scheduledTimestamp.toString(), }); From 85d9fa5ac1a155fa4008b44df8d7789235fcdb39 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Sat, 4 Oct 2025 09:57:08 +0000 Subject: [PATCH 3/9] Transitioned from Plan to Build mode Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/Ob3gzfQ From 116c0f547b3c07d82c8dfae9504d3ec4ca706cb6 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Sat, 4 Oct 2025 09:58:33 +0000 Subject: [PATCH 4/9] Update application design with a modern and simple theme Define design guidelines including color palette, typography, layout system, and component library for a modern SaaS dashboard look. 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/Ob3gzfQ --- design_guidelines.md | 155 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 design_guidelines.md diff --git a/design_guidelines.md b/design_guidelines.md new file mode 100644 index 0000000..2b9fdf5 --- /dev/null +++ b/design_guidelines.md @@ -0,0 +1,155 @@ +# Social Flow - Design Guidelines + +## Design Approach + +**Selected Framework:** Design System Approach inspired by modern SaaS dashboards (Linear, Buffer, Notion) with Material Design principles for data-rich interfaces. + +**Core Philosophy:** Professional productivity tool prioritizing clarity, efficiency, and visual hierarchy in dark mode with sophisticated blue/purple branding. + +## Color Palette + +**Dark Mode (Primary Theme):** +- Background Base: 222 20% 8% +- Surface Elevated: 222 18% 12% +- Surface Card: 222 16% 15% +- Border Subtle: 222 12% 20% + +**Brand Colors:** +- Primary Blue: 215 85% 58% +- Primary Purple: 265 75% 62% +- Gradient Accent: Linear gradient from Primary Blue to Primary Purple + +**Functional Colors:** +- Success Green: 142 76% 48% +- Warning Orange: 35 95% 58% +- Error Red: 0 85% 62% +- Info Cyan: 195 85% 55% + +**Text Hierarchy:** +- Primary Text: 0 0% 95% +- Secondary Text: 222 10% 65% +- Tertiary Text: 222 8% 48% + +## Typography + +**Font Family:** +- Primary: 'Inter' from Google Fonts (400, 500, 600, 700) +- Monospace: 'JetBrains Mono' for timestamps and metrics + +**Scale:** +- Headings H1: text-3xl font-semibold +- Headings H2: text-2xl font-semibold +- Headings H3: text-xl font-medium +- Body Large: text-base +- Body: text-sm +- Captions: text-xs text-secondary + +## Layout System + +**Spacing Primitives:** Tailwind units of 2, 4, 6, 8, 12, 16 (e.g., p-4, gap-6, mt-8) + +**Grid Structure:** +- Sidebar: Fixed width 280px (w-70) on desktop, collapsible on mobile +- Main Content: Flexible with max-w-7xl container +- Dashboard Grid: grid-cols-1 md:grid-cols-2 lg:grid-cols-3 with gap-6 + +**Container Widths:** +- Dashboard sections: max-w-7xl with px-6 to px-8 +- Form containers: max-w-2xl +- Content cards: Full width within grid columns + +## Component Library + +### Sidebar Navigation +- Dark surface (Background Base) with subtle border-right +- Logo + app name at top (h-16) +- Navigation items with icons (Heroicons) + labels +- Active state: Primary gradient background with 12% opacity, blue text +- Hover: Surface Elevated background +- Bottom section: User profile card with avatar, name, settings icon +- Spacing: py-2 between items, px-4 horizontal padding + +### Dashboard Cards +- Background: Surface Card with rounded-xl +- Border: 1px solid Border Subtle +- Shadow: Soft shadow (shadow-lg with low opacity) +- Padding: p-6 +- Header: Flex justify-between with title (text-lg font-semibold) + action button +- Content spacing: space-y-4 internally + +### Post Scheduling Interface +- Calendar view: Week/month grid with date cells +- Post cards: Compact cards showing thumbnail + caption preview + platform badges (FB/IG) +- Drag-and-drop visual indicators +- Time slots: Hourly breakdown with scheduled posts + +### Analytics Cards +- Metric cards: Large number (text-3xl font-bold) + label + trend indicator +- Charts: Use Chart.js with gradient fills matching brand colors +- Grid layout for KPIs: 4 columns on desktop, responsive down + +### Forms & Inputs +- Input fields: Surface Elevated background, border Border Subtle, rounded-lg, px-4 py-3 +- Focus state: Primary Blue border, subtle glow +- Labels: text-sm font-medium mb-2, Secondary Text color +- Textarea: min-h-32 for post composition +- File upload: Dashed border drop zone with center icon and text + +### Buttons +- Primary: Gradient background (blue to purple), text-white, rounded-lg, px-6 py-3, font-medium +- Secondary: Border Primary Blue, text Primary Blue, transparent background +- Ghost: Transparent, hover Surface Elevated +- Icon buttons: w-10 h-10, rounded-lg, center content + +### Platform Badges +- Small pills (px-3 py-1, rounded-full, text-xs font-medium) +- Facebook: Blue background (215 85% 58% with 15% opacity), blue text +- Instagram: Purple background (265 75% 62% with 15% opacity), purple text + +### Status Indicators +- Dots with colors: w-2 h-2 rounded-full +- Scheduled: Primary Blue +- Published: Success Green +- Failed: Error Red +- Draft: Tertiary Text + +### Data Tables +- Header row: Surface Elevated background, font-medium, uppercase text-xs +- Rows: Border-bottom subtle, hover Surface Card +- Padding: px-6 py-4 +- Alternating backgrounds for better readability + +## Animations + +**Minimal & Purposeful:** +- Page transitions: Fade-in only (150ms) +- Card hover: Subtle lift (translateY -2px, 200ms) +- Button interactions: Scale 0.98 on active +- Navigation: Smooth color transitions (200ms) +- No distracting scroll animations or complex effects + +## Images + +**Hero Section:** None - Dashboard-first interface prioritizing immediate utility + +**Avatar & Thumbnails:** +- User avatars: w-10 h-10, rounded-full with border +- Post thumbnails: aspect-video, rounded-lg, object-cover +- Platform logos: Use official brand SVGs at 20x20 or 24x24 + +**Empty States:** +- Illustration placeholders for "No posts scheduled", "No analytics data" +- Center aligned with icon, heading, and CTA button +- Subtle grayscale illustrations maintaining professional tone + +## Key Screens Layout + +**Dashboard:** 3-column grid with Overview metrics (top row), Recent Posts card, Upcoming Schedule card, Quick Analytics + +**Calendrier:** Full-width calendar component, left sidebar filter (platforms, status), right panel for selected post details + +**Nouvelle Publication:** Center form (max-w-2xl), left preview panel showing platform-specific mockups, sticky publish/schedule buttons + +**Analytiques:** Metric cards grid (4 cols), followed by full-width charts for engagement over time, best posting times heatmap + +**Paramètres:** Two-column layout, left navigation tabs, right content panels \ No newline at end of file From e90f8930b35858d031f8198956b0255b24991705 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Sat, 4 Oct 2025 10:01:12 +0000 Subject: [PATCH 5/9] Update the application's appearance with a modern and clean theme Refactor the sidebar component to use a new theme, updating color palettes, typography, and layout for a more modern and readable user interface. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/Ob3gzfQ --- client/src/components/sidebar.tsx | 107 ++++++++----- client/src/index.css | 253 ++++++++++++++++++++---------- 2 files changed, 237 insertions(+), 123 deletions(-) diff --git a/client/src/components/sidebar.tsx b/client/src/components/sidebar.tsx index 657e772..0346ec4 100644 --- a/client/src/components/sidebar.tsx +++ b/client/src/components/sidebar.tsx @@ -4,13 +4,13 @@ import { useQuery, useMutation } from "@tanstack/react-query"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { useToast } from "@/hooks/use-toast"; import { Button } from "@/components/ui/button"; +import { Avatar, AvatarFallback } from "@/components/ui/avatar"; export default function Sidebar() { const [location] = useLocation(); const [, setLocation] = useLocation(); const { toast } = useToast(); - // Charger la session utilisateur const { data: session } = useQuery<{ id: string; username: string; role: string }>({ queryKey: ["/api/auth/session"], retry: false, @@ -18,7 +18,6 @@ export default function Sidebar() { const isAdmin = session?.role === "admin"; - // Mutation pour déconnexion const logoutMutation = useMutation({ mutationFn: async () => { const res = await apiRequest("POST", "/api/auth/logout", {}); @@ -39,7 +38,7 @@ export default function Sidebar() { { icon: PlusCircle, label: "Nouvelle publication", href: "/new", badge: null }, { icon: Calendar, label: "Calendrier", href: "/calendar", badge: null }, { icon: Images, label: "Médiathèque", href: "/media", badge: null }, - { icon: Users, label: "Pages gérées", href: "/pages", badge: "8" }, + { icon: Users, label: "Pages gérées", href: "/pages", badge: null }, { icon: Bot, label: "Assistant IA", href: "/ai", badge: null }, ]; @@ -49,21 +48,25 @@ export default function Sidebar() { ]; return ( -