Interactive demo · synthetic dataEvery record on this page is fabricated.
Seasonal Catalog Media Pipeline
Eight command-line tools that move a season’s images onto a wholesale catalogue: the shell simulated, the matching real.
The production code behind this demo is my own work — design, implementation, the naming convention and the dry-run-by-default rule, the season run and its runbooks.
PICK A TOOL
Map exported swatch filenames onto the loader's convention. Anything it cannot place is left alone.
python rename_swatches.py ./M27THE EIGHT TOOLS, AND WHICH OF THEM CAN WRITE
The blast radius is the architecture. One tool that did all of this would have to be trusted all at once; eight of them can be trusted separately, and three of them cannot do damage at all.
rename_swatches.py · DRY-RUN BY DEFAULT
renames exported swatch files to the loader's convention
photos_sync.py · DRY-RUN BY DEFAULT
matches colourway photos, uploads only what is missing
ws_link.py · DRY-RUN BY DEFAULT
assigns swatches to colourways and PATCHes the ACF fields
find_missing.py · READ-ONLY BY CONSTRUCTION
which sw-* files never made it into the media library
photo_audit.py · READ-ONLY BY CONSTRUCTION
colourways with no photo, photos with no colourway
inspect_media.py · READ-ONLY BY CONSTRUCTION
duplicate -1 / -2 slugs from an accidental double upload
media_refresh.py · DRY-RUN BY DEFAULT
delete-then-upload, one file at a time
probe_upload.py · WRITES ITS OWN TESTS, THEN DELETES THEM
finds the host's real upload ceiling, then removes every test it made
What is real, and what is simulated
Runs in your browser
- The order-insensitive token set-match for colourways and the ordered seq-match for product names, which accepts an abbreviation as a prefix in either direction — 'CR' in a filename satisfies 'CREW'
- The one-character-tolerant typo fallback, and the two-character miss it correctly refuses
- The score matrix: normalised whole-label and per-segment containment, with the 0.85 penalty on any segment but the first
- Both assignment algorithms — greedy per colourway, and the global best-total bitmask dynamic program with its greedy fallback above sixteen swatches
- The 0.25 floor, the leftover de-duplication rule, and the file-size diff that decides NEW / CHANGED / SAME
Ported by hand from the Python, function by function, against the behaviour the source's own comments claim. 56 tests assert it, including the one that matters: over a single score matrix the greedy pass strands a colourway and the dynamic program does not.
Simulated
- The shell itself. Nothing on this page executes a process; the terminal replays a stage script at a readable pace
- WordPress REST and ACF, every upload, every delete, the Pillow downscale and the host's size rejection
- The catalogue: twelve products, twenty-three filenames, five swatch tiles and every media id are invented for this page. The tiles are flat colours drawn as SVG — there is no product photography here