Cache garden images through Cloudinary
Created by: jedmund
Summary
- Upload external garden images to Cloudinary at save time using URL-based upload, storing the Cloudinary URL in
imageUrland preserving the original in a newsourceImageUrlfield - Handle image lifecycle: upload on create, re-upload on change (cleaning up old), delete on item deletion, with graceful fallback to external URLs if upload fails
- Add a one-time backfill endpoint (
POST /api/admin/garden/backfill-images) to migrate existing items - Remove now-unnecessary external image domains (IGDB, AniList, TMDB, TVDB, OpenLibrary) from CSP
img-src
Test plan
-
Create a new garden item via search — image should be uploaded to Cloudinary, sourceImageUrlstores original -
Edit an item and change its image — old Cloudinary image deleted, new one uploaded -
Edit an item without changing image — no re-upload -
Delete an item with a Cloudinary image — image cleaned up -
Run backfill endpoint — existing items migrated to Cloudinary -
Verify upload failure falls back to external URL gracefully