Skip to content

API: person thumbnail is the uncropped original — expose the cropped derivative #1432

Description

@jonfroehlich

Problem

/api/v1/people/<url_name>/ and the nested person object in /api/v1/projects/<slug>/people/ both expose exactly one image field, thumbnail, and it points at the raw uploaded file:

https://makeabilitylab.cs.washington.edu/media/person/20190927_Jon_Froehlich-1018.jpg

The site's own templates don't render that file. They render the easy-thumbnails derivative that honors the per-person crop box set in the admin:

/media/person/20190927_Jon_Froehlich-1018.jpg.48x48_q85_box-3222%2C927%2C6621%2C4326_crop_detail_upscale.jpg

So an API consumer gets a photo that ignores the crop, at full source resolution.

Impact

Project Sidewalk's new About page (ProjectSidewalk/SidewalkWebpage#4631) builds its team roster from this API. Measured payload for the 13 cards it renders, each displayed in a 128 px circle:

person thumbnail bytes
kashvigoel 15,342,361
jonfroehlich 11,230,931
ishajagadish 3,191,534
delphinelabbe 1,610,399
manaswisaha 692,250
judyshanley 360,704
davidjacobs 251,841
mikeysaugstad 241,345
yochaieisenberg 212,686
kiannamckeesteen 154,948
chuli 147,137
kotarohara 36,961
joyhammel 6,386
total 33.5 MB

For comparison, the cropped 48×48 derivative the ML site serves for the second row is 1,448 bytes.

Framing suffers too: with only an uncropped source, a consumer's object-fit: cover cuts wherever the original photo happens to be centered — which is the exact problem the crop box exists to solve.

Why a consumer can't work around it

The crop box appears in the derivative URL but not in the payload — the person serializer's only image key is thumbnail:

['bio', 'bluesky', 'current_department', 'current_school', 'current_title', 'first_name', 'github',
 'google_scholar', 'id', 'last_name', 'linkedin', 'mastodon', 'middle_name', 'name', 'orcid',
 'personal_website', 'threads', 'thumbnail', 'twitter', 'url', 'url_name']

And derivatives are generated server-side by the template tag, so a size the site has never rendered 404s — even with the correct box:

$ curl -s -o /dev/null -w '%{http_code}\n' \
  'https://makeabilitylab.cs.washington.edu/media/person/20190927_Jon_Froehlich-1018.jpg.256x256_q85_box-3222%2C927%2C6621%2C4326_crop_detail_upscale.jpg'
404

The project page requests 48×48 and 64×64. Both are too small for a 128 px avatar on a 2× display.

Ask

Add a cropped thumbnail URL to the person serializer:

  • at ≥256×256, so a consumer can render a 128 px avatar sharply on a HiDPI display;
  • on both /api/v1/people/<url_name>/ and the nested person object in /api/v1/projects/<slug>/people/ — the roster reads the nested one, and having it in only one place means a second request per member just for a photo URL.

Exposing the raw crop box alongside it would be useful, but isn't sufficient on its own given the 404 above.

Follow-on to #1426. Related: #1417, where Open Graph share images don't honor the crop box either.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions