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.
Problem
/api/v1/people/<url_name>/and the nestedpersonobject in/api/v1/projects/<slug>/people/both expose exactly one image field,thumbnail, and it points at the raw uploaded file: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:
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:
thumbnailbytesFor 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: covercuts 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:And derivatives are generated server-side by the template tag, so a size the site has never rendered 404s — even with the correct box:
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:
/api/v1/people/<url_name>/and the nestedpersonobject 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.