Photo Workflow
Photo Workflow — Multi-Image par Espèce
Comment ajouter des images aux fiches bestiary. Hybride local-first : tes photos perso priorité absolue, iNaturalist pour le reste.
Principe
Local-first est meilleur que API runtime pour 4 raisons :
- Zéro broken image (vs Wikimedia hotlink 403 que nous avons eu)
- Vercel CDN cache = chargement instantané
- Brand-fit max quand ce sont tes photos
- Offline-ready
Structure des dossiers
public/photos/species/<slug>/
├── 01-portrait.jpg ← TES PHOTOS PERSO (priorité 1)
├── 02-feeding.jpg
├── 03-mue.jpg
├── inat-01.jpg ← iNat fetch auto (fallback)
├── inat-02.jpg
└── inat-03.jpg
Convention : tes photos perso commencent par NN-context.jpg. Le script iNat utilise prefix inat-NN.jpg.
Workflow
A) Tu prends une photo perso (priorité 1)
# Tu drop dans le dossier
public/photos/species/phidippus-regius/01-portrait-macro.jpg
public/photos/species/phidippus-regius/02-feeding-drosophila.jpg
# Update auto frontmatter
npm run photos:scan
# → met à jour primaryImage + images[] dans le frontmatter md
B) Auto-fetch iNat (espèces sans photos perso)
# Fetch 5 photos par espèce depuis iNaturalist (top observations research-grade)
npm run photos:fetch-inat-multi
# Options
npm run photos:fetch-inat-multi -- --species=odontomachus-simillimus # 1 espèce
npm run photos:fetch-inat-multi -- --limit=3 # 3 photos seulement
npm run photos:fetch-inat-multi -- --force # re-fetch tout
npm run photos:fetch-inat-multi -- --cc-by-only # licence CC BY only (skip CC BY-NC)
Ce que ça fait :
- Pour chaque espèce, query iNat
/observationsfiltré partaxon_name, sorted by votes (research-grade) - Download top 5 photos vers
/public/photos/species/<slug>/inat-NN.jpg - Update frontmatter
primaryImage+images[]+imageAttribution - Skip espèces déjà populées (sauf
--force) - Polite delay 250ms entre downloads + 500ms entre espèces
C) Photos perso override les iNat (priorité)
Quand tu drop tes photos perso (01-portrait.jpg), elles prennent automatiquement la place de la primaryImage. Le script photos:prefer-personal enforce cette règle.
npm run photos:prefer-personal
# → primaryImage = première photo qui ne commence PAS par "inat-"
Convention nommage
Tes photos perso (priorité)
01-portrait.jpg ← cover, plein cadre
02-feeding-drosophila.jpg ← contexte (avec nom de la proie)
03-mue.jpg
04-couple.jpg
05-detail-yeux.jpg
06-2026-05-15-shoot-night.jpg ← option avec date pour tracking chronologique
iNat photos auto
inat-01.jpg
inat-02.jpg
...
Attribution & licence
iNaturalist photos = CC BY ou CC BY-NC principalement.
Notre usage :
- Stockage local autorisé pour personal/educational use
- Attribution stockée dans
imageAttributionfrontmatter - Affiché sur fiche bestiary detail page
- Si commercial use plus tard → re-fetch avec
--cc-by-only(filtre uniquement licences commerciales-friendly)
Coût stockage
- Image iNat medium (~500px) : 50-150 KB chacune
- 239 espèces × 5 photos = ~1195 photos × 100KB avg = ~120 MB
- Vercel limit : 1 GB par deploy → on a beaucoup de marge
- Git LFS pas nécessaire (sub-1MB par fichier)
Workflow recommandé
Setup initial (one-shot)
npm run photos:fetch-inat-multi
git add public/photos/species/
git commit -m "feat: bulk fetch iNat photos for 239 species"
git push
Quand tu acquières un spécimen
# 1. Prends 5-10 macros sur ton M2 Mac Mini Frigate ou téléphone
# 2. Drop dans le dossier
mkdir -p public/photos/species/<slug>/
cp ~/photos/recent/*.jpg public/photos/species/<slug>/
# 3. Renomme avec convention
# 01-portrait.jpg, 02-feeding.jpg, etc.
# 4. Update frontmatter
npm run photos:scan
# 5. Commit
git add public/photos/species/<slug>/
git commit -m "feat: photos perso pour <slug>"
git push
Quarterly refresh iNat (option)
# Re-fetch top observations (peut avoir de meilleures photos depuis)
npm run photos:fetch-inat-multi -- --force
Pourquoi pas Pexels / Unsplash
Searche “Phidippus regius” sur Pexels → résultats : araignées génériques (Wolf spider, House spider, etc.), pas Phidippus regius.
iNat = species-specific, observations identifiées par communauté scientifique. Quand tu cherches Phidippus regius, tu obtiens 3389 observations vérifiées de Phidippus regius, pas une photo générique.
Pourquoi pas Wikimedia hotlink
Wikimedia bloque hotlinking dans certains cas (referrer checks). On a eu 3 URLs broken → setup actuel évite ce risque.
Liens
- iNat API observations
- CC BY-NC license
- Existing scripts :
/scripts/fetch-inat-images.ts(1 photo, legacy),/scripts/photos-scan.ts,/scripts/photos-prefer-personal.ts
docs/lab/photo-workflow.md · sync: npm run docs:sync