--- phase: 17-object-storage plan: 03 subsystem: ui tags: [s3, minio, presigned-urls, image-migration, react, client-components] requires: - phase: 17-object-storage provides: "S3 storage service and API response enrichment with presigned imageUrl" provides: - "All client components display images via presigned URLs from API responses" - "One-time migration script for local uploads/ to MinIO" affects: [client-image-display, deployment] tech-stack: added: [] patterns: ["imageUrl prop on card/list components", "local preview via createObjectURL for new uploads"] key-files: created: - scripts/migrate-images-to-minio.ts modified: - src/client/components/ImageUpload.tsx - src/client/components/ItemCard.tsx - src/client/components/CandidateCard.tsx - src/client/components/CandidateListItem.tsx - src/client/components/ComparisonTable.tsx - src/client/components/CollectionView.tsx - src/client/components/ItemForm.tsx - src/client/components/CandidateForm.tsx - src/client/routes/setups/$setupId.tsx - src/client/routes/threads/$threadId.tsx key-decisions: - "Use createObjectURL for immediate preview after upload, presigned URL for existing images" - "Migration script preserves originals - manual deletion after verification" patterns-established: - "imageUrl prop: all image-displaying components accept imageUrl from API, not construct /uploads/ paths" - "ImageUpload dual-source: localPreview (just uploaded) > imageUrl (presigned) > null (placeholder)" requirements-completed: [IMG-02, IMG-03] duration: 4min completed: 2026-04-05 --- # Phase 17 Plan 03: Client Image URL Migration and Migration Script Summary **Replaced all client /uploads/ path references with presigned S3 URLs and created one-time image migration script** ## Performance - **Duration:** 4 min - **Started:** 2026-04-05T10:25:33Z - **Completed:** 2026-04-05T10:30:00Z - **Tasks:** 2 - **Files modified:** 11 ## Accomplishments - All 6 client image components now use imageUrl from API responses instead of constructing /uploads/ paths - Zero /uploads/ references remain in client code - Migration script reads uploads/ directory and uploads each file to MinIO preserving filenames - ImageUpload component supports both presigned URLs (existing images) and local object URLs (new uploads) ## Task Commits Each task was committed atomically: 1. **Task 1: Update client components to use imageUrl from API responses** - `8c64bf9` (feat) 2. **Task 2: Create image migration script** - `6f40f94` (feat) ## Files Created/Modified - `src/client/components/ImageUpload.tsx` - Added imageUrl prop, local preview via createObjectURL - `src/client/components/ItemCard.tsx` - Added imageUrl prop, use presigned URL for display - `src/client/components/CandidateCard.tsx` - Added imageUrl prop, use presigned URL for display - `src/client/components/CandidateListItem.tsx` - Added imageUrl to interface, use presigned URL - `src/client/components/ComparisonTable.tsx` - Added imageUrl to interface, use presigned URL - `src/client/components/CollectionView.tsx` - Pass imageUrl to ItemCard - `src/client/components/ItemForm.tsx` - Pass imageUrl to ImageUpload from item record - `src/client/components/CandidateForm.tsx` - Pass imageUrl to ImageUpload from candidate record - `src/client/routes/setups/$setupId.tsx` - Pass imageUrl to ItemCard - `src/client/routes/threads/$threadId.tsx` - Pass imageUrl to CandidateCard - `scripts/migrate-images-to-minio.ts` - One-time migration from uploads/ to S3 ## Decisions Made - Used createObjectURL for immediate preview after upload (presigned URL not available until next GET) - Migration script does not auto-delete originals (user deletes manually after verification) ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None ## User Setup Required None - no external service configuration required. Migration script usage documented in script header comments. ## Next Phase Readiness - Full stack now uses MinIO for image storage - Migration script ready to run for existing deployments: `bun run scripts/migrate-images-to-minio.ts` - All client and server /uploads/ references eliminated --- *Phase: 17-object-storage* *Completed: 2026-04-05*