Pack images HallesX — Nano Banana (gemini-2.5-flash-image)
Le manifest (source de vérité) : scripts/images-manifest.mjs — partagé entre le générateur et la console /admin/images (statut, prompts, coût restant en direct).
Générer
GEMINI_API_KEY=xxx node scripts/generate-images.mjs # tout (~122 img, ~4,76 $)
GEMINI_API_KEY=xxx node scripts/generate-images.mjs --only=photo/ # les photos seulement
GEMINI_API_KEY=xxx node scripts/generate-images.mjs --only=cat/ # une famille
Relance = ne régénère que les manquantes. Les images tombent dans public/img/** et le site les affiche automatiquement (fallback élégant si absentes : SVG MarketHeroArt, dégradés de filière).
Ordre conseillé pour la première génération (valider la cohérence tôt) :
--only=photo/cat/— les 10 cagettes photo : c'est la série la plus exigeante en cohérence (même cagette, même angle) → vérifier avant de continuer ;--only=hero/puis--only=photo/scene/;- le reste sans filtre.
Les DEUX styles verrouillés
Chaque prompt = bloc de style (identique mot pour mot) + sujet écrit sur mesure pour cette image précise. Deux systèmes, jamais mélangés sur une même surface :
| 🎨 Illustration de marque | 📷 Photo réaliste | |
|---|---|---|
| Rôle | l'identité — héros, landings, halles, saisons | la preuve — filières, scènes métier, tailles de culture |
| Bloc | STYLE : flat éditorial français, palette charte stricte (#F7F4EC/#17803D/#7CB944/#D96B3F/#F6B93B/#211F1A), lumière du matin à gauche, ombres 45°, grain papier | STYLE_PHOTO : 35 mm plein format, f/2.8, lumière naturelle du matin à gauche, étalonnage chaud crème, grain argentique léger, sincérité documentaire (bois usé, produits imparfaits, comptoirs zinc) |
| Interdits | texte, lettres, chiffres, logos, filigranes | idem + « no staging gloss, no plastic perfection » |
La même direction de lumière (matin, gauche) dans les deux styles : les deux mondes cohabitent sur le site sans friction.
Un prompt sur mesure par image
Plus aucun sujet générique : chaque photo précise cadrage, focale, heure, matière, micro-détail narratif. Exemples réels du manifest :
photo/cat/champignons.png— « The same weathered pine crate, same angle, lined with straw… one cep cut in half showing its white flesh, moody but warm light. »photo/scene/palette.png— « …pulling a chest-high stack of produce crates across the wet concrete of a wholesale hall at 5 a.m. 35mm low angle, halogen lamps flaring softly, breath visible in the cold air. »photo/taille/grande-exploitation.png— « low drone at dawn… aerial 45-degree angle, patchwork of greens, epic but human. »
Astuce de série : les 10 cagettes photo commencent toutes par « The same weathered pine crate, same angle » — la répétition littérale du même ancrage visuel est ce qui fait tenir la collection.
Tous les prompts sont lisibles un par un dans /admin/images (dépliables, avec statut et vignette dès génération).
Les bonnes pratiques appliquées
- Style verrouillé répété mot pour mot — la technique n°1 de cohérence.
- Jamais de texte dans les images (
no text, no letters) : la typo reste Fraunces/DM Sans dans le HTML — netteté parfaite, i18n possible, zéro faute. - Le bon format par emplacement (ratios natifs du modèle) : héros pleine largeur 21:9 · héros de landing/OG 16:9 · cartes filières/halles 4:3 · scènes métier 3:2.
- La déclinaison, pas la variation : même cagette, même angle sur les 10 filières — en illustration comme en photo.
- QA après génération : ouvrir /admin/images, vérifier chaque série en vignettes ; une image qui casse la série → supprimer le fichier, ajuster son prompt dans le manifest, relancer
--only=<chemin>(0,04 $).
L'inventaire (122 images)
Illustrations (99)
- 5 héros — home 21:9, cote 4:3, halles 21:9, pro 16:9, la chaîne 21:9
- 10 cagettes de filière (4:3) + 8 scènes métier (3:2) + 3 tailles (4:3)
- 4 saisons (21:9)
- 52 landings + 7 features + 12 halles (16:9)
Photos réalistes (21) — nouvelles, prompt individuel
- 10 cagettes photo
photo/cat/*(4:3) — la même cagette de pin, 50 mm, par filière - 8 scènes reportage
photo/scene/*(3:2) — acheteur, tire-palette 5 h du matin, camion frigo, vélo-cargo Lyon, carreau à l'aube, pesée, criée, facture du soir - 3 tailles de culture
photo/taille/*(4:3) — balcon doré, micro-ferme dans la brume, grande exploitation au drone
Câblage déjà en place
lib/img.ts→siteImg(rel): image si le fichier existe, sinon fallback.- Branché : héros de la cote, héros des 52 landings, cartes des places (/marches), bandeau « la chaîne » (home). Les photos ont vocation aux cartes produits/filières et aux pages « pour qui » côté preuve — à câbler après validation visuelle du lot 1.
Coûts : ce qui reste, ce qui se rend, ce qui s'anime
Règle d'or : on ne paie jamais deux fois la même image.
| Famille | Génération | Persistance | Coût récurrent |
|---|---|---|---|
| Pack illustrations + photos (122 images Nano Banana) | une seule fois, en local | committé dans public/img/**, copié dans l'image Docker, cache 30 j | 0 € après les ~4,76 $ initiaux |
| Vignettes OG (~300, avec données : prix, séances…) | au build, par next/og (satori, local) | fichiers statiques du build, cache 24 h | 0 € — aucun appel d'API, jamais |
| Vidéos données (Remotion, à venir) | offline (cron nightly ou manuel), rendu local/CI | MP4 committés dans public/video/** | 0 € — le rendu est du CPU CI, pas une API |
Le générateur est idempotent : il saute toute image déjà présente. Pour refaire UNE image : supprimer le fichier puis relancer avec --only=<chemin>.
Remotion (vidéos avec données réelles) — plan
Même philosophie que les OG : composition React qui lit data/rnmdb, rendue hors requête (cron hebdo), sortie MP4 committée et servie statiquement. Premiers candidats : « la semaine du marché » 15 s pour la home et les réseaux, et une déclinaison par halle. À scaffolder quand on veut la première vidéo.