automation Case study
Product Image Pipeline
A watch and jewellery retailer with a catalogue in the tens of thousands had hundreds of products with no photo at all. A product without a photo does not sell and should not be indexed, so I built two things: a rule that takes it off the shelf cleanly, and a pipeline that finds a photo, gets it through Photoshop on the owner's PC and puts it back.
The business problem
Hundreds of products were published with no featured image. Each one was a thin page for a search engine and a dead end for a customer. The photos existed somewhere, on official brand stores and dealer sites, but nobody had the time to find them one by one, and any tool that did it automatically had to be trusted never to touch a photo that was already there.
The hard part was not the download. Photoshop runs on the owner's PC, not on a server. The bot server that can find and fetch an image cannot open Photoshop, and the owner cannot be asked to stand over a queue. The pipeline had to hand work across that gap, wait for a human for as long as it takes, and say honestly what state every product was in.
What I delivered
- A catalogue rule: a published product with no featured image is drafted with a reason flag, and its URL answers with a 302 to the nearest stocked category, not a 404, until a photo arrives. The same tool drafts a whole set, closes and noindexes an emptied category, and restores exactly that set later; it also answered a trademark notice against one brand. Both behaviour plugins carry kill switches.
- A state-machine pipeline on the bot server with seven tables and a five-minute tick: search the configured source sites for a reference photo, validate and de-duplicate it, ship the raw to the owner's PC, take the finished image back, attach it and republish the product.
- An agent on the owner's PC that moves raws into the folder for the Photoshop batch and moves finished images out, plus an agent API on the bot server that it talks to. Confirmation is per folder, not per photo: the owner deletes what he rejects and the rest goes up.
- A hard policy called ONLY_EMPTY: the pipeline fills an empty image slot and never replaces an existing photo.
- A Bulk Composite script for Photoshop that turns raw watch photos into hero and gallery JPEGs, with 107 mocked test cases that run on every change.
- REST endpoints on the shop for the bot server: list products with no image, find and attach media, report image status. They authenticate with a token header and an IP allowlist, which is what let the bot server's root SSH key to the site be revoked and deleted.
Technical approach
- Matching is scored, not guessed. A SKU match, or the reference in the URL or title, scores 100; a variant scores 80; nothing under 75 is accepted. A candidate must be at least 600px with an aspect ratio between 0.5 and 2, and duplicates are dropped by sha256 and by perceptual hash within a distance of 6.
- Failures back off at 1, 5, 15 and 60 minutes and then land in NEEDS_REVIEW instead of looping. After a fourteen-hour stall, caused by a slash inside one reference that produced an invalid path and killed the whole tick, each phase now runs in its own try/except, so one bad product cannot stop the rest.
- The human step is designed around absence. The owner's agent once went quiet for over fourteen hours while its status column still read ONLINE, so the dashboard now ages the last check-in. When more than 20 raws are waiting and the agent has been quiet for over three hours, one Telegram message goes out with the exact command to run, and never more than once in twelve hours.
- The Photoshop script's default changed under evidence. The latest release made native Magic Wand white-background removal the default because the Photoshop AI commands hang on the owner's PC after two photos; AI cutout stays available as an explicit mode.
- Sourcing was measured before it was extended. About half of the image-less products had no source site at all. Adding two official regional stores for one brand raised its coverage from 32% to 45%; a large dealer site added only a handful of matches; the supplier portal turned out to have no image field. Those numbers decide where the next sourcing effort goes.
Result and evidence
Honest scope. The pipeline has been live since September 2026 and is verified end to end on one product: found, shipped to the owner's PC, processed, attached, republished. The Photoshop script's 107 mocked tests run on every change; a run on a batch of real photos on the owner's PC is still owed, and my own Photoshop cannot be driven from the shell, so I claim no real-host run. At the mid-September count, hundreds of raws were sitting on the owner's PC waiting for the batch and none had come out the other side. Nothing else has been measured yet.
Commercial value
A product with no photo is a page that cannot sell and should not be indexed. Drafting it with a redirect protects the category today; the pipeline brings it back with a photo without the owner opening a single product page. The same pattern transfers to any retailer with a large catalogue and missing photos, and to distributors syncing supplier imagery.
Readable implementation brief
implementation_brief {
project: "Product Image Pipeline"
status: "live since September 2026; verified end to end on one product"
rule: "no featured image -> drafted with a reason flag;
URL 302s to the nearest stocked category, never a 404"
pipeline: "bot server, 7-table state machine, 5-minute tick,
agent API; owner-PC agent moves raws in, finished out"
policy: "ONLY_EMPTY; an existing photo is never replaced"
matching: "SKU 100 / reference 100 / variant 80, threshold 75;
>= 600px, aspect 0.5-2; dedupe sha256 + pHash <= 6"
retry: "1m / 5m / 15m / 1h, then NEEDS_REVIEW"
photoshop: "Bulk Composite, latest release; native white-background removal
default, AI cutout explicit; 107 mocked tests per change"
access: "token header + IP allowlist; root SSH key revoked"
}What this project shows
The part I would want a reviewer to look at is the boundary with the human. An agent that reports ONLINE while silent for fourteen hours is worse than no status at all; ageing the check-in and nudging with the exact command, at most twice a day, is the difference between a pipeline that runs and one that quietly waits forever.
Two defaults were set by evidence rather than taste: the AI cutout gave way to Magic Wand because it hung on the real machine, and ONLY_EMPTY was fixed before the first image moved, because a pipeline that can overwrite a good photo will eventually do so.