feat: fruit overview with thumbnails and card layout (story #07) #7

Merged
julia merged 1 commits from feature/07-improve-fruit-overview into main 2026-06-19 07:19:00 +00:00
Owner

Summary

  • Auto-crop thumbnails on image upload (Go stdlib only): find non-background bounding box, pad 5px, scale to ≤300px, encode JPEG
  • Add thumbnail_data BYTEA column to both image tables (migration 000004)
  • New thumbnail serve endpoints for fruit images and publication fruit images (fallback to full data if no thumbnail)
  • New POST /api/v1/admin/backfill-thumbnails to retroactively generate thumbnails for existing images
  • ListFruits response now includes synonyms and thumbnail_url per fruit
  • Replace FruitList.vue table with responsive FruitCard grid (thumbnail + name + OSDB ID + type + synonyms)

Test plan

  • Upload fruit image → thumbnail_data non-null in DB
  • GET /thumbnail endpoint → responds with JPEG ≤300px, smaller than original
  • Backfill endpoint populates all rows missing thumbnail_data
  • GET /api/v1/fruits → each fruit with image has thumbnail_url
  • Fruit with no image → thumbnail_url: null, card shows placeholder
  • Publication fruit image thumbnail endpoint works
  • FruitList.vue shows card grid with thumbnails
  • go test ./... green

🤖 Generated with Claude Code

## Summary - Auto-crop thumbnails on image upload (Go stdlib only): find non-background bounding box, pad 5px, scale to ≤300px, encode JPEG - Add `thumbnail_data BYTEA` column to both image tables (migration 000004) - New thumbnail serve endpoints for fruit images and publication fruit images (fallback to full data if no thumbnail) - New `POST /api/v1/admin/backfill-thumbnails` to retroactively generate thumbnails for existing images - `ListFruits` response now includes synonyms and `thumbnail_url` per fruit - Replace `FruitList.vue` table with responsive `FruitCard` grid (thumbnail + name + OSDB ID + type + synonyms) ## Test plan - [ ] Upload fruit image → `thumbnail_data` non-null in DB - [ ] `GET /thumbnail` endpoint → responds with JPEG ≤300px, smaller than original - [ ] Backfill endpoint populates all rows missing thumbnail_data - [ ] `GET /api/v1/fruits` → each fruit with image has `thumbnail_url` - [ ] Fruit with no image → `thumbnail_url: null`, card shows placeholder - [ ] Publication fruit image thumbnail endpoint works - [ ] `FruitList.vue` shows card grid with thumbnails - [ ] `go test ./...` green 🤖 Generated with [Claude Code](https://claude.com/claude-code)
julia added 1 commit 2026-06-19 07:16:37 +00:00
- Auto-crop thumbnails on image upload (Go stdlib, no external deps):
  find non-background bounding box, pad 5px, scale to ≤300px, encode JPEG
- Add thumbnail_data BYTEA column to fruit_images and publication_fruit_images
- New GET /api/v1/fruits/:id/images/:imageId/thumbnail endpoint (fallback to full data)
- New GET /api/v1/publications/:id/fruit-images/:imgId/thumbnail endpoint
- New POST /api/v1/admin/backfill-thumbnails to retroactively generate thumbnails
- ListFruits response now includes synonyms and thumbnail_url per fruit
- Replace FruitList table with responsive FruitCard grid (thumbnail + name + OSDB ID + type + synonyms)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
julia merged commit b6f2ac06ae into main 2026-06-19 07:19:00 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julia/osdb-1-claude-opusplan#7