Trois défauts se cumulaient : des réponses bien plus larges que nécessaire,
aucun index en base, et des boucles de requêtes là où une seule suffisait.
Réponses
- /api/scheduled-posts renvoyait la ligne `social_pages` entière, jetons
d'accès Facebook et TikTok compris, jusque dans le navigateur. Seules les
colonnes réellement affichées sont désormais sélectionnées.
- Le filtre de dates est poussé en SQL. Il était appliqué en JavaScript après
avoir chargé tout l'historique — que le client ne bornait jamais. Le
calendrier demande maintenant les six semaines affichées, le sélecteur de
date les créneaux à venir, le bloc « publications récentes » ses 90 jours.
- /api/media accepte `limit` et `offset` (sans eux, réponse inchangée : des
écrans doivent retrouver un média par son identifiant). La médiathèque
pagine côté serveur au lieu de tout charger pour afficher cinq vignettes, et
l'écran de création ne demande que les douze médias qu'il propose. Le total
voyage dans l'en-tête X-Total-Count pour garder le compteur juste.
Index
- server/migrate.ts est le seul script exécuté au démarrage et n'en créait
aucun ; ceux de migration-docker.sql ne servaient à rien, ce fichier n'étant
monté nulle part. Postgres n'indexant pas les clés étrangères, le calendrier,
l'historique et le scheduler parcouraient les tables entières. S'y ajoutent
deux index partiels pour les boucles de fond : publications en attente et
suivi asynchrone TikTok.
Requêtes
- /api/stats lisait quatre tables entières pour en compter les lignes : c'est
désormais quatre COUNT filtrés.
- Les vues d'administration listaient les utilisateurs puis interrogeaient les
pages de chacun ; une seule requête les remplace.
- getPostWithMedia et l'API externe chargeaient les médias un par un.
- /api/reels/ongoing chargeait tous les posts de l'utilisateur pour n'en garder
que ceux en cours de génération, toutes les trois secondes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qns6Gcpd95bCHWUxySh4Ew
Deux corrections demandées ensemble.
1. Vignettes vidéo
Le planificateur supprime la vidéo locale une fois publiée, alors que la
ligne `media` survit pour l'historique. L'interface tentait donc de lire
un fichier disparu pour en extraire une image : d'où les avertissements
« Video thumbnail generation failed » et les tuiles vides.
Une vignette JPEG est désormais extraite à la création du reel, dans les
deux flux de génération, et stockée à part : elle reste disponible quand
la vidéo ne l'est plus. La purge quotidienne la nettoie en même temps que
la ligne qu'elle illustre. L'extraction est tolérante à l'échec — une
vignette manquante dégrade l'affichage mais ne fait jamais échouer une
publication — et le composant retombe sur son icône de remplacement pour
les médias créés avant ce changement. La fonction d'extraction, jusque-là
privée à la route Remotion, devient un service partagé.
2. Erreurs de compilation préexistantes (27 → 0)
- remotion-video.tsx (bureau et mobile) : les composants Select étaient
utilisés sans être importés, ce qui faisait planter le sélecteur de voix
à l'exécution.
- external.ts : fileSize et aiGenerated étaient transmis dans un type que
le schéma ne déclare pas, et ne fonctionnaient que par conversion
implicite de PostgreSQL.
- reels.ts : l'interface MusicTrack, référencée mais jamais déclarée dans
ce module.
- remotion.ts : chromiumOptions.args retiré. Remotion ne lit jamais cette
clé, les drapeaux Chrome qu'elle contenait n'atteignaient donc pas le
navigateur.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018uUPZ1GNpEkYB1dpXHYPek
La route /api/ai/generate connaissait la cause exacte de l'échec
(configuration absente, clé invalide, crédits épuisés, modèle inconnu)
mais la remplaçait par un « Failed to generate text » en 500, et
l'interface affichait de son côté un message figé. Sans accès aux logs
du serveur, l'utilisateur n'avait donc aucun moyen de savoir quoi
corriger.
Le motif renvoyé par OpenRouter est désormais extrait, tronqué et
propagé jusqu'au bandeau d'erreur, avec un code HTTP qui distingue un
problème de configuration (400) d'un refus du service tiers (502).
La clé API n'apparaît à aucun moment dans ces messages.
Même traitement pour /api/reels/generate-text, qui souffrait du même
masquage.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018uUPZ1GNpEkYB1dpXHYPek
Ajoute la gestion multi-comptes TikTok et permet d'envoyer la même vidéo
sur plusieurs pages Facebook ET plusieurs comptes TikTok en une seule
publication.
Un compte TikTok vit dans social_pages comme une page Facebook : il hérite
donc des permissions par utilisateur, de la planification et du calendrier.
Trois particularités de l'API TikTok structurent l'implémentation :
- pas de jeton saisi à la main : chaque compte passe par OAuth, et
l'access token (24h) est renouvelé via le refresh token (1 an) avant
chaque publication ;
- la publication est asynchrone : l'upload rend un publish_id, et un
poller récupère l'identifiant définitif du post ;
- creator_info doit être interrogé avant chaque envoi pour ne demander
qu'un niveau de confidentialité réellement autorisé sur le compte.
Serveur :
- service TikTok (OAuth, creator_info, upload FILE_UPLOAD par chunks,
suivi de statut) et routes de connexion/configuration
- schéma : platform 'tiktok', refresh token et scopes sur social_pages,
publish_id/publish_status sur scheduled_posts, table tiktok_config
- routage par plateforme dans les deux flux de reels et le planificateur
- cron de suivi des publications, token manager et analytics adaptés
Client :
- connexion et reconnexion des comptes TikTok depuis « Pages gérées »
- sélection combinée pages Facebook / comptes TikTok à la publication
- configuration de l'application TikTok dans les paramètres (admin)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018uUPZ1GNpEkYB1dpXHYPek
The SPA's session check (/api/auth/session) is cached indefinitely by
react-query (staleTime: Infinity, no refetch on focus/interval), so once a
protected page mounts successfully, the app never re-verifies auth. If the
server-side session later becomes invalid (server restart with in-memory
sessions, cookie/session expiry, etc.), every subsequent API call
(pages, scheduled-posts, audio-tracks, media, media/upload, ...) starts
failing with 401 in a loop with no way for the user to recover short of a
manual page reload.
Add a shared handleUnauthorized() in queryClient.ts that redirects to
/login on any non-auth API 401, wired into both the shared fetch helpers
(apiRequest/getQueryFn) and the raw fetch() calls used for file uploads
and Remotion rendering, which also lacked this recovery path. Also add the
missing credentials: "include" to those raw fetch() calls for consistency
with the rest of the app's API requests.
Old Cloudinary URLs no longer load (account full). The new MediaThumbnail
component handles broken URLs gracefully with a fallback icon, and uses
<video preload="metadata"> for local video files to show the first frame.
- New component: client/src/components/media-thumbnail.tsx
- Updated: new-reel.tsx, new-post.tsx, media-upload.tsx,
edit-scheduled-post-dialog.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrates a new DateTimePicker component into the new post page, replacing the old datetime-local input. This component allows for selecting specific dates and times, and also visually indicates dates with pre-existing scheduled posts. The internal state and API request payload have been updated to correctly handle Date objects instead of strings.
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/aGnsIb5
Introduce a new 'both' post type allowing simultaneous publishing to Facebook and Instagram feeds and stories. This includes UI updates for selecting post types, backend logic for splitting 'both' posts into separate feed and story entries, and the ability to delete scheduled posts. The changes also include a new 'Pages gérées' link in the sidebar and necessary database schema updates.
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/WuFXYmm
Introduce new state variables for generated variants and post text. Update the AI generation success handler to set generated variants and modify the post creation logic to use the `postText` state. Add a new `handleUseVariant` function and a UI section to display and select AI-generated text variations.
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/sjuGm8z