A product photo pipeline
A shop needs the same photograph at four sizes in two shapes, every week, from a folder that is never quite the same twice. That is a rule set, and it should be written once.
What a catalogue asks for
The sizes are the easy part. What makes catalogue work different from every other bulk job is that two of the outputs have to be the same shape as each other across products that were not photographed the same way. A grid of tiles where one is taller than the rest is the thing a customer notices before they notice the products.
| Output | Roughly | Fit | Why that fit |
|---|---|---|---|
| Grid tile | 400 × 400 | cover, centre | Every tile identical. A ragged grid reads as a broken page. |
| Listing image | 800 × 800 | cover, centre | Same square, enough detail for a hover or a tap. |
| Zoom view | 1600 on the long edge | contain | Here the whole object matters more than the shape. |
| Cart thumbnail | 120 × 120 | cover, centre | Small enough that the crop is invisible and the bytes are free. |
Three of the four are squares filled by cropping, and one is the picture untouched but smaller. That split is the whole design: cropping where consistency matters, containing where completeness matters, and never arguing about it per product.
The rule stack, in order
Rules run in order and every rule a file matches writes a file, so one photograph leaves this stack as four. Written out as the card headers print them:
1 Cart thumb all files box 120x120 cover c webp q70 {parent}/thumb.webp
2 Grid tile all files box 400x400 cover c webp q78 {parent}/grid.webp
3 Listing all files box 800x800 cover c webp q82 {parent}/listing.webp
4 Zoom all files long edge 1600 contain webp q86 {parent}/zoom.webpQuality climbs with size, which is deliberate and the opposite of what people expect. A 120-pixel tile hides compression artefacts inside four pixels of product; a 1600-pixel zoom is the one image a customer looks at closely before deciding to spend money, and it is the only place the extra bytes are earned.
The order of the four is not load-bearing — every matching rule writes its file regardless — but it is the order the plan lists them in, and reading a plan sorted small to large makes a missing output obvious.
When one product needs something different
Put the exception above the general rule and give it a pattern. A matcher of **/wide/* catches anything inside a folder called wide, wherever it sits in the drop, so a handful of panoramic products can take a 3:2 tile while the rest stay square:
1 Wide tile **/wide/* box 600x400 cover c webp q78 {parent}/grid.webp
2 Grid tile all files box 400x400 cover c webp q78 {parent}/grid.webpBoth rules match the panoramic files, so both write, and both write to the same name — which the plan catches as a collision rather than letting the second quietly win. The fix is to narrow the general rule to everything else, or to set the collision policy so the later file wins and accept that the plan will strike the first row through. Either is fine; discovering it at write time would not have been.