What needs to be done?
Currently, when a user updates an existing design and saves, we upload NEW screenshots to Cloudflare R2 but don't delete the old ones. This means each design update creates 2 additional files (full-size + thumbnail), leading to orphaned screenshots accumulating in storage.
Example scenario:
- User creates design ID 15 →
design-15-1234567-full.jpg, design-15-1234567-thumb.jpg (2 files)
- User edits and saves design 15 →
design-15-1234568-full.jpg, design-15-1234568-thumb.jpg (2 NEW files)
- User edits and saves again →
design-15-1234569-full.jpg, design-15-1234569-thumb.jpg (2 MORE files)
- Result: 6 files in storage, but only the last 2 are actually used
Goal: Automatically delete old screenshots when uploading new ones during design updates, so each design only has 2 files in storage at any time.
Priority: LOW - Cloudflare R2 free tier is 10 GB/month. Current usage is minimal (~1.75 MB), but this prevents long-term storage bloat. At current scale (~500KB per design), we can store ~20,000 designs before hitting 10GB.
Which page/component?
Files involved:
src/features/designs/useDesign.ts - saveDesign() function
src/lib/uploadScreenshots.ts - Upload logic
src/lib/downloadScreenshot.ts - Delete helper function (already exists but unused)
- Backend:
DesignController.cs, R2Service.cs
Tasks
Backend
Frontend
Key principle: Delete happens AFTER successful upload. If upload fails, old screenshots remain.
Notes
Current implementation status:
- New screenshots upload successfully
- Database updates with new URLs
- Backend delete endpoint exists (
DELETE /api/Design/screenshots/{fileName})
- Delete helper function exists (
deleteScreenshotFromR2() in lib/downloadScreenshot.ts)
- Delete logic NOT called in
useDesign.ts - old screenshots accumulate
Solution location:
Update src/features/designs/useDesign.ts saveDesign() function to:
- Fetch current design before upload (to get old URLs)
- Upload new screenshots
- Update database
- Delete old screenshots
Error handling: Screenshot deletion should NEVER block a save - it's cleanup, not critical path.
Alternative approach: Batch cleanup job (weekly) to find orphaned files (files in R2 not in database).
Related endpoints:
GET /api/Design/{id} - Fetch current design
POST /api/Design/screenshots/upload-urls - Get presigned URLs
PUT /api/Design/{id} - Update design
DELETE /api/Design/screenshots/{fileName} - Delete old screenshot
Estimated effort: 1-2 hours
Risk: Low. Deletion failure doesn't break saves.
Testing: Verify in Cloudflare R2 dashboard that old files are actually deleted after updates.
What needs to be done?
Currently, when a user updates an existing design and saves, we upload NEW screenshots to Cloudflare R2 but don't delete the old ones. This means each design update creates 2 additional files (full-size + thumbnail), leading to orphaned screenshots accumulating in storage.
Example scenario:
design-15-1234567-full.jpg,design-15-1234567-thumb.jpg(2 files)design-15-1234568-full.jpg,design-15-1234568-thumb.jpg(2 NEW files)design-15-1234569-full.jpg,design-15-1234569-thumb.jpg(2 MORE files)Goal: Automatically delete old screenshots when uploading new ones during design updates, so each design only has 2 files in storage at any time.
Priority: LOW - Cloudflare R2 free tier is 10 GB/month. Current usage is minimal (~1.75 MB), but this prevents long-term storage bloat. At current scale (~500KB per design), we can store ~20,000 designs before hitting 10GB.
Which page/component?
Files involved:
src/features/designs/useDesign.ts-saveDesign()functionsrc/lib/uploadScreenshots.ts- Upload logicsrc/lib/downloadScreenshot.ts- Delete helper function (already exists but unused)DesignController.cs,R2Service.csTasks
Backend
DeleteFile()method toIR2Service.csandR2Service.csDELETE /api/Design/screenshots/{fileName}endpoint toDesignController.csFrontend
useDesign.tssaveDesign(), fetch current design's screenshot URLs BEFORE uploading new onesdeleteScreenshotFromR2()for old URLsKey principle: Delete happens AFTER successful upload. If upload fails, old screenshots remain.
Notes
Current implementation status:
DELETE /api/Design/screenshots/{fileName})deleteScreenshotFromR2()inlib/downloadScreenshot.ts)useDesign.ts- old screenshots accumulateSolution location:
Update
src/features/designs/useDesign.tssaveDesign()function to:Error handling: Screenshot deletion should NEVER block a save - it's cleanup, not critical path.
Alternative approach: Batch cleanup job (weekly) to find orphaned files (files in R2 not in database).
Related endpoints:
GET /api/Design/{id}- Fetch current designPOST /api/Design/screenshots/upload-urls- Get presigned URLsPUT /api/Design/{id}- Update designDELETE /api/Design/screenshots/{fileName}- Delete old screenshotEstimated effort: 1-2 hours
Risk: Low. Deletion failure doesn't break saves.
Testing: Verify in Cloudflare R2 dashboard that old files are actually deleted after updates.