# Phase 5: Image Handling - Context **Gathered:** 2026-03-15 **Status:** Ready for planning ## Phase Boundary Fix image display throughout the app (images upload but don't render), redesign the upload UX with a hero image preview area and placeholder icons, and add image display to gear cards, candidate cards, and setup item lists. No new image features (galleries, editing, tagging) — those would be separate phases. ## Implementation Decisions ### Image preview area (item form) - Move image from bottom of form to a full-width hero area at the top - 4:3 landscape aspect ratio (matches ItemCard's existing aspect-[4/3]) - When no image: light gray background with centered Lucide icon (ImagePlus or Camera) and "Click to add photo" text below - When image exists: full-width image with object-cover, small circular X button in top-right to remove - Clicking the image opens file picker to replace (same behavior as clicking placeholder) ### Card placeholders - All cards (items and candidates) show the 4:3 image area always — consistent card heights in grid - When no image: light gray (gray-50/gray-100) background with the item's category icon centered - Category icons are currently emoji — use whatever is current (Phase 6 will migrate to Lucide) - Candidate cards get the same placeholder treatment as item cards ### Upload interaction - Click only — no drag-and-drop (keeps it simple for side panel form) - Spinner overlay centered on hero area while uploading - No client-side image processing (no crop, no resize) — CSS object-cover handles display - CandidateForm gets the same hero area redesign as ItemForm ### Image in detail/setup views - Clicking uploaded image in form opens file picker to replace (no lightbox/zoom) - Setup item lists show small square thumbnails (~40px) with rounded corners next to item name - Setup thumbnails show category icon placeholder when item has no image ### Image display bug fix - Investigate and fix root cause of images uploading but not rendering (likely path/proxy issue) - This is prerequisite work — fix before redesigning the UX ### Claude's Discretion - Exact placeholder icon choice (ImagePlus vs Camera vs similar) - Spinner animation style - Exact gray shade for placeholder backgrounds - Transition/animation on image load - Error state design for failed uploads ## Existing Code Insights ### Reusable Assets - `ImageUpload` component (`src/client/components/ImageUpload.tsx`): Existing upload logic with file validation, apiUpload call, preview, and remove button — needs restructuring into hero area pattern - `ItemCard` (`src/client/components/ItemCard.tsx`): Already renders imageFilename with `aspect-[4/3]` but skips image area when null — needs placeholder addition - `CandidateCard` / `CandidateForm`: Candidate equivalents that need same treatment - `apiUpload` helper in `lib/api.ts`: Upload function already works ### Established Patterns - Images stored as UUID filenames in `./uploads/` directory - Server serves `/uploads/*` via `hono/bun` serveStatic - Vite dev proxy forwards `/uploads` to `http://localhost:3000` - Image upload API at `POST /api/images` returns `{ filename }` (201 status) - `imageFilename` field on items and candidates — string or null - 5MB max, JPG/PNG/WebP accepted ### Integration Points - `src/client/components/ItemForm.tsx`: Move ImageUpload from bottom to top, redesign as hero area - `src/client/components/CandidateForm.tsx`: Same hero area redesign - `src/client/components/ItemCard.tsx`: Add placeholder when imageFilename is null - `src/client/components/CandidateCard.tsx`: Add placeholder when imageFilename is null - `src/client/routes/setups/$setupId.tsx`: Add small thumbnails to setup item list - Server static file serving: Verify `/uploads/*` path works in both dev and production ## Specific Ideas - Hero area should feel like a product photo section — clean, prominent, image-first - Placeholder with category icon adds visual meaning even before images are uploaded - Consistent 4:3 aspect ratio across hero area and cards keeps everything aligned - Setup thumbnails should be compact (40px square) — don't dominate the list layout ## Deferred Ideas None — discussion stayed within phase scope --- *Phase: 05-image-handling* *Context gathered: 2026-03-15*