Skip to content
Twenty One Media
webAugust 31, 2026

The Crop Is a Separate Decision from the Photo

When the new studio portraits came back from the August shoot, we had thirteen edited frames to choose from for the homepage founder block. Picking the photo took thirty seconds: colour over B&W for the homepage, seated over standing, black shirt over green tee. Done.

Finding the right crop took longer.

The Photo and the Slot Are Different Problems

The homepage has a 4:5 card that renders at 384px wide. When we looked at the selected frame as a 6000px export in Lightroom, we saw one thing. When we cut it into a next/image with fill and sized it to the actual card, we saw something else.

We made three cuts before landing on one that worked:

  • Tight: Amputated the crossed leg. Reads as a passport photo in a small card, not a seated portrait.
  • Full: Centred the subject in the frame. Left too much background, pushed him off-axis relative to the text block.
  • Mid: Kept the pose, kept the face, left negative space on the inner edge. Works.

None of this was obvious from the source at full resolution. The tight cut looks fine in Lightroom. At 384px it looks like a mugshot. The full cut seems to give the subject room until you see it next to a column of text and realize he's staring at the wrong edge.

The rule we've landed on: evaluate photos at the actual slot dimensions before committing to anything. Every other size is a different photo.

Iterating the Position

After settling on mid, Isaac wanted him further left. The negative space should sit on the inner edge, leading toward the text. We re-cut the source JPEG, shifting the crop window 350px to the right.

At +350px the composition worked. Pushing to +600px the crossed knee started clipping the left edge. There was no arithmetic that found that ceiling. His grey trousers and the studio floor merged at the same brightness value, so we couldn't measure where the leg ended. We found the limit by rendering candidates at the true 384px slot.

Final crop: 2976x3720+472+780. Isaac confirmed it, and the reference points are now in HANDOFF.md: +252 was the original centred cut, +602 was too far left, +600 is roughly where the knee starts clipping. The next person who touches this photo doesn't re-derive it from scratch.

Why We Re-Cropped the File Instead of Using CSS

When next/image delivers an image as avif, it generates variants keyed on the source URL and the requested width. Cropping with object-position in CSS means the full-width source still flows through the optimizer. You pay to deliver every pixel, then throw most of them away in the browser.

If you re-crop the JPEG, the optimizer only sees the pixels you want. The avif is smaller, nothing is wasted, and what gets cached is what you actually need.

One thing we tested rather than assumed: overwriting a file in public/ on Vercel invalidates the optimizer cache. We renamed the file on the first re-crop as a precaution against stale avifs. That caution was unnecessary. The subsequent re-crop kept the same filename and the delivered avif updated correctly. The stale-cache failure mode we were thinking of belongs to the PWA service worker, which is a separate system.

The Frame That Isn't Wired Yet

The shoot has one frame we haven't placed: a tight colour headshot, the kind that works at 100px. It belongs on the OG social image, the contact page, and the ops audit PDFs. We know where it goes.

That's how a photo session works in practice. You get more usable assets than you can place in one push. The unused frames don't expire. They go in the handoff notes with a destination, and they get wired when the surface is ready.