Clear the backlog: 10 Codex prompts for your own files
photo-batch
every product photo renamed, resized and ready for the web
How to use it
Codex only. Nothing else to install. Save the prompt as a file and run it, or paste it straight into Codex.
codex exec -C "your folder" - < the-prompt.md
It does the whole job in one pass on your own machine and writes the result into the folder you pointed it at.
The prompt
---
name: photo-batch
description: Turns a folder of product photos into web-ready copies at the right sizes and formats, correctly named, with a report of anything that fails a shop's image rules. Originals are never touched.
---
# Every product photo renamed, resized and ready for the web
You point it at a folder of photos. You get back a new folder of web-ready copies at the sizes and formats a shop actually needs, named properly, plus a list saying which original became which file and which photos are too small to use.
Run it on your own machine, over your own files, in one pass:
```
codex exec -C "the folder" - < the-prompt.md
```
## What it does
1. **Open the source folder read only, and write everywhere else:** all output goes to a new `web/` folder created beside the source folder, never inside it. Before writing anything, record every original's file name, byte size and modified time in `photo-report.csv`, so check 2 can prove nothing was touched. If `web/` already exists and holds files, stop and say so rather than writing over them.
2. **Inventory every photo first:** one row per file in `photo-report.csv` with pixel width, pixel height, file size in MB, format, and the EXIF orientation value. Photos come off phones sideways, and orientation is the reason a batch of "correct" images ends up rotated on the shop.
3. **Fix rotation before resizing, not after:** apply the EXIF orientation and remove the tag. In Pillow that is `ImageOps.exif_transpose(im)`, documented as "If an image has an EXIF Orientation tag, other than 1, transpose the image accordingly, and remove the orientation data". Resizing a sideways photo first gives you a correctly rotated image with the wrong dimensions.
4. **Produce three sizes on the long edge, and never enlarge:** 2048 px for the main image, 1024 px for listing tiles, 512 px for thumbnails. Shopify's own help says "For square product images, a size of 2048 x 2048 px usually displays best". Pillow's `thumbnail()` is the safe call because it produces an image "no larger than the given size" and preserves the aspect ratio, so a small original stays small instead of being blown up into a blurry one. Every photo smaller than 2048 px on the long edge is listed in the report as needing a reshoot.
5. **Write WebP first and a JPEG beside it, and only add AVIF on request:** WebP is supported in "All versions of Chrome, Edge, Firefox, Opera, and Safari" according to MDN's image format guide, so it is safe as the main file. AVIF support starts at "Chrome 85, Edge 121, Opera 71, Firefox 93, and Safari 16.1", so the same page says you should include fallbacks using the `<picture>` element. If the shop cannot serve a `<picture>` element, do not produce AVIF at all: it is a file nobody will see.
6. **Use the encoder defaults unless the owner says otherwise, and never guess a quality number:** Pillow saves WebP at quality 80 and AVIF at quality 75 by default, and its WebP `method` defaults to 4 on a 0 to 6 speed against quality scale. Say in the report which numbers were used. If a saved file is bigger than the original, keep the original format for that photo and note it.
7. **Rename to a pattern the shop can sort:** `product-slug_<longedge>.<ext>`, lower case, hyphens instead of spaces, no accents, no brackets, no `#` and no `&`. Every output row in `photo-report.csv` names the original it came from, so nothing becomes unfindable. Never reuse an output name: if two originals produce the same slug, add `-2` and flag both in the report.
8. **Pass the colour profile through and strip location data:** Pillow only writes the ICC profile and EXIF block if you hand them to `save()`, and its documentation warns that "If a writer doesn't recognise an option, it is silently ignored", so a mistyped option leaves you with washed out colours and no error. Pass `icc_profile=im.info.get("icc_profile")` and do not carry GPS tags into a public file.
9. **Check each output against the shop's published rules and flag failures:** Google's Merchant Center requirements are at least 500 x 500 pixels, around 1500 x 1500 recommended, no image over 64 megapixels or 16 MB, and no watermarks, logos, pricing or calls to action laid over the picture. Shopify accepts up to 5000 x 5000 px or 25 megapixels and under 20 MB. Anything failing a rule gets a plain-English reason in the report, for example "too small for Google Shopping at 420 x 420".
## Then it checks
1. The file arithmetic balances: number of output files equals number of usable originals multiplied by the number of sizes multiplied by the number of formats, minus any skipped and named in the report. Print the sum.
2. Every original's byte size and modified time match what was recorded in step 1. If a single one has changed, an original was written to, and that is a failure whatever else worked.
3. No output is larger in pixels than the original it came from, and each output's width divided by its height matches the original's to within one per cent, which is what catches a squashed image.
4. Three outputs are opened and looked at: right way up, right subject, not stretched, colours not washed out.
5. Every output filename is unique, is lower case, contains no spaces and appears exactly once in `photo-report.csv` beside the original it came from.
6. Every photo listed as failing a shop rule has the specific rule and the actual measurement written next to it, not just the word "failed".
Any check fails: name it, redo that step once. Failed twice: say what is wrong and stop.
## Rules
- Public information only. This job needs no internet: the photos stay on the owner's machine, and nothing is uploaded to an online converter or compression service.
- Never invent a fact, a number or a quote. Do not state a compression saving you have not measured, and do not claim a size requirement that is not in the shop's own published rules.
- **Never overwrite an original, and never write inside the source folder.** If the only way to finish is to modify a source file, stop instead.
- Do not remove or add a watermark, a logo, or anyone else's branding. If the photos came from a supplier or a stock library, the licence decides what may be published, and this skill prepares the files so a professional can check that. It is not legal advice on image rights.
- Anything that cannot be produced is reported, never quietly skipped. A photo too small for the requested size is named in the report with its actual dimensions.
## Built from
- MDN Web Docs, "Image file type and format guide", https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types, last modified 28 August 2026: took the browser support statements for WebP and AVIF, and the instruction to include a `<picture>` fallback when using AVIF.
- web.dev, "Learn Images: WebP", https://web.dev/learn/images/webp, last updated 1 February 2023: took the fact that WebP uses a single quality value "expressed from 0-100, just like JPEG", which is why the skill sets one number and reports it rather than tuning per photo.
- Pillow documentation, https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html and https://pillow.readthedocs.io/en/stable/reference/ImageOps.html, read 7 September 2026: took the WebP quality default of 80, the AVIF quality default of 75, the WebP method default of 4, the behaviour of `thumbnail()` which never enlarges and preserves aspect ratio, `exif_transpose()` for orientation, and the warning that an unrecognised save option is silently ignored.
- Google Merchant Center Help, "Image requirements", https://support.google.com/merchants/answer/6324350, read 7 September 2026: took the 500 x 500 pixel minimum, the roughly 1500 x 1500 recommendation, the 64 megapixel and 16 MB caps, the ban on watermarks and promotional overlays, and the rule that the product fills between 75 and 90 per cent of the frame.
- Shopify Help Center, "Product media types", https://help.shopify.com/en/manual/products/product-media/product-media-types, read 7 September 2026: took the 2048 x 2048 px recommendation for square product images, the 5000 x 5000 px and 25 megapixel ceiling, and the 20 MB file size limit.
Built from the best public work on this
Sources for photo-batch
Every source below was opened on 7 September 2026. Where a page shows its own date, that date is given. No source is cited that could not be loaded.
MDN Web Docs, "Image file type and format guide"
https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types, page last modified 28 August 2026.
This is the primary reference for which image format a browser will actually display, and it is the reason photo-batch writes WebP as the main file rather than AVIF. The page states WebP support as "All versions of Chrome, Edge, Firefox, Opera, and Safari", and AVIF support as "Chrome 85, Edge 121, Opera 71, Firefox 93, and Safari 16.1". Those two sentences are the whole decision in step 5: WebP needs no thought, AVIF does.
It also carries the caveat that became the second half of step 5: "Note that when using AVIF, you should include fallbacks to formats with better browser support (i.e., using the `<picture>` element)." A small shop on a hosted platform often cannot edit the markup to add a `<picture>` element, and in that case generating AVIF files produces work nobody will ever see, so the skill refuses to make them rather than making them by default.
The same page's advice to provide a JPEG or PNG fallback for WebP is why step 5 writes a JPEG beside every WebP instead of assuming the shop template will cope.
web.dev, "Learn Images: WebP"
https://web.dev/learn/images/webp, last updated 1 February 2023.
Read for the encoding advice rather than the support tables. The useful fact taken from it is that WebP is controlled by "a single 'quality' value, expressed from 0-100, just like JPEG", which is why photo-batch sets one quality number for the whole run and prints it in the report, rather than pretending to tune each photo individually. The page's worked example gives a concrete measurement, 208418 bytes at quality 80, and no percentage saving against JPEG, which is why the skill's rules forbid claiming a compression saving that has not been measured on the owner's own photos.
The companion AVIF page at https://web.dev/learn/images/avif, same date, was also read. It was deliberately not used for numbers: it references Netflix and Cloudinary studies showing "significant reductions in file sizes" but gives no figures, so there is nothing quotable to build a threshold on.
Pillow documentation
https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html, https://pillow.readthedocs.io/en/stable/reference/Image.html and https://pillow.readthedocs.io/en/stable/reference/ImageOps.html, all read 7 September 2026.
Pillow is the library the run will actually use, and four documented behaviours decide how the steps are written.
The save defaults come from the file formats page: WebP `quality` is an "Integer, 0-100, defaults to 80", WebP `method` is a "Quality/speed trade-off (0=fast, 6=slower-better). Defaults to 4", and AVIF `quality` is an "Integer, 0-100, defaults to 75". Step 6 uses those numbers as written instead of inventing a house setting, and prints them so the owner can see what was used.
`Image.thumbnail()` is documented as making an image "no larger than the given size" and it "calculates an appropriate thumbnail size to preserve the aspect of the image". That single sentence is the whole of the never-enlarge rule in step 4: with `thumbnail()` a 900 px photo asked for 2048 px simply stays at 900 px, whereas a plain `resize()` would upscale it into a soft, obviously amateur product shot. The same entry warns that the method "modifies the Image object in place", which is why the skill works on an opened copy and never near the source file.
`ImageOps.exif_transpose()` is documented as: "If an image has an EXIF Orientation tag, other than 1, transpose the image accordingly, and remove the orientation data." That is step 3, and it is placed before resizing on purpose.
The last one is a trap rather than a feature. The `save()` reference states that "Keyword options can be used to provide additional instructions to the writer. If a writer doesn't recognise an option, it is silently ignored." A misspelled `icc_profile` or `quality` therefore produces a finished, wrong-looking file and no error at all, which is why step 8 passes the profile explicitly and why check 4 makes someone look at three of the outputs.
Google Merchant Center Help, "Image requirements"
https://support.google.com/merchants/answer/6324350, read 7 September 2026.
The published rules a product photo must meet to appear in Google Shopping, and the only hard external thresholds in the skill. Taken from it: images must be "At least 500 x 500 pixels", Google advises you "provide images around 1500 x 1500 pixels or above to ensure best performance in all listing formats", "No image larger than 64 megapixels", and "No image file larger than 16 MB". Also taken: the prohibition on overlays, specifically "watermarks, brand names, logos", calls to action and pricing, and promotional adjectives, plus the framing rule that the product should occupy "no less than 75%, but no more than 90%, of the full image".
Step 9 checks each output against these and writes the failure in plain words with the actual measurement, because "too small" is useless to a shop owner and "too small for Google Shopping at 420 x 420" tells them exactly which photo to reshoot.
Shopify Help Center, "Product media types"
https://help.shopify.com/en/manual/products/product-media/product-media-types, read 7 September 2026.
Used for the main working size. Shopify states "For square product images, a size of 2048 x 2048 px usually displays best", which is where step 4's 2048 px long edge comes from, and it gives the platform ceilings: "any size up to 5000 x 5000 px, or 25 megapixels" and a "file size smaller than 20 MB". Its format list confirms WebP is accepted for product media, which matters because there is no point producing a format the platform will reject on upload.
Best public prompt we found for this job
The strongest public artefact is **MDN's "Image file type and format guide"** (last modified 28 August 2026), because it is the only source that tells you what will happen in a real visitor's browser rather than what compresses well in a test.
The one line worth copying verbatim into any image prompt:
"Note that when using AVIF, you should include fallbacks to formats with better browser support (i.e., using the `<picture>` element)."
Want this running in your business?
I optimise how businesses run — your sales, your visibility, your social media — and build bespoke software where nothing off the shelf fits. The first conversation is free. Work starts from £150 a day.
Foxera