Files
GearBox/.planning/milestones/v2.2-phases/29-image-presentation/29-CONTEXT.md
Jean-Luc Makiola 2853477a75
All checks were successful
CI / ci (push) Successful in 1m15s
CI / e2e (push) Has been skipped
CI / deploy (push) Has been skipped
chore: archive v2.2 User Experience Polish milestone
Phases 28-31 archived to milestones/v2.2-phases/
Requirements and roadmap snapshots archived to milestones/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:00:35 +02:00

5.8 KiB

Phase 29: Image Presentation - Context

Gathered: 2026-04-12 Status: Ready for planning

## Phase Boundary

Replace hard-crop image display (object-cover) with fit-within framing across all image surfaces. Images are scaled to fit inside the aspect ratio container with adaptive dominant-color background fill. Users can adjust image framing via a zoom+pan editor available during upload and from item detail pages.

## Implementation Decisions

Fit Strategy & Fill Treatment

  • D-01: Replace object-cover with object-contain across all image surfaces — images scale to fit inside the frame without cropping.
  • D-02: Fill remaining space with the image's dominant color extracted server-side. This creates an adaptive background that makes the image feel intentional rather than letterboxed.
  • D-03: Dominant color extraction happens server-side on upload, stored as a field (e.g., dominantColor: '#abc123') on the item/globalItem record. No client-side computation.
  • D-04: Existing images need a backfill migration — process all existing images to extract and store their dominant color.

Aspect Ratio Policy

  • D-05: Claude's discretion on whether to keep different ratios (4:3 cards, 16:9 global detail) or unify. Choose what looks best for gear product images.

Scope of Changes

  • D-06: Apply the new presentation to every surface where images appear: ItemCard, GlobalItemCard, CandidateCard, CandidateListItem, item detail pages, global item detail pages, comparison table, ImageUpload preview, catalog search overlay. Full consistency — no exceptions.

User Crop Positioning

  • D-07: Implement a zoom + pan editor — users can zoom in/out and drag to position the image within the frame.
  • D-08: Editor available in two places: during image upload (ImageUpload component) and from item detail/edit pages (re-adjustable anytime).
  • D-09: Crop settings stored per-image (not per-context). One set of zoom/pan coordinates applied everywhere the image appears. Store as fields on the image record (e.g., cropZoom, cropX, cropY).
  • D-10: When crop settings exist, they override the default object-contain behavior — the image is displayed at the user-specified zoom and position within the frame, with dominant color fill for any remaining space.

Claude's Discretion

  • Zoom+pan editor component implementation (library vs custom)
  • Dominant color extraction algorithm (Sharp, node-vibrant, or similar)
  • DB schema for crop fields (on items table, globalItems table, or a separate image_settings table)
  • Backfill migration strategy (background job, on-demand, or one-time script)
  • Whether to generate server-side thumbnails for performance or keep CSS-only rendering

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Image Display Components (all need updating)

  • src/client/components/ItemCard.tsxaspect-[4/3] + object-cover (line ~164-170)
  • src/client/components/GlobalItemCard.tsxaspect-[4/3] + object-cover (line ~31-37)
  • src/client/components/CandidateCard.tsx — uses object-cover pattern
  • src/client/components/CandidateListItem.tsx — uses object-cover pattern
  • src/client/components/ImageUpload.tsxaspect-[4/3] + object-cover (line ~72-79)
  • src/client/components/ComparisonTable.tsx — uses object-cover pattern
  • src/client/components/LinkToGlobalItem.tsx — uses object-cover pattern
  • src/client/components/CatalogSearchOverlay.tsx — uses object-cover pattern

Image Detail Pages

  • src/client/routes/items/$itemId.tsxaspect-[4/3] + object-cover (line ~245-250)
  • src/client/routes/global-items/$globalItemId.tsxaspect-[16/9] + object-cover (line ~65-70)
  • src/client/routes/threads/$threadId/candidates/$candidateId.tsx — uses object-cover

Server-Side Image Handling

  • src/server/routes/images.ts — Image upload endpoint
  • src/server/services/storage.service.ts — S3/MinIO storage service

Database Schema

  • src/db/schema.ts — Items, globalItems tables (need dominantColor + crop fields)

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • ImageUpload component — upload preview with aspect ratio container. Will host the zoom+pan editor.
  • S3/MinIO storage pipeline — images uploaded via /api/images, stored in MinIO, served from /uploads/.
  • Consistent aspect-[4/3] pattern across cards — refactoring can target this pattern systematically.

Established Patterns

  • All image containers use aspect-[ratio] + overflow-hidden + object-cover on the <img>. Switching to object-contain with background color is a targeted CSS change per component.
  • No existing image processing on upload — adding dominant color extraction introduces a new server-side processing step.

Integration Points

  • src/server/routes/images.ts — Add dominant color extraction after upload
  • src/db/schema.ts — Add dominantColor field to items and globalItems
  • All card/detail components — Update image rendering to use contain + dominant color bg
  • ImageUpload component — Add zoom+pan editor overlay

</code_context>

## Specific Ideas
  • The adaptive dominant-color background should make images feel like they belong in the frame, not like they're floating in empty space.
  • The zoom+pan editor should be intuitive — drag to move, pinch/scroll to zoom. Not a complex crop tool.
  • Existing images all need backfill for dominant color — this affects catalog items seeded by MCP agents too.
## Deferred Ideas

None — discussion stayed within phase scope


Phase: 29-image-presentation Context gathered: 2026-04-12