From One Folder to Three CSVs and a Zip: Four Python Scripts That Finish Assets
The failure had no drama to it. I had 39 finished products sitting in one folder, and when I tried to submit the first batch to an upload form, the platform rejected the CSV instantly. Wrong header. I fixed the header by hand, resubmitted, and got rejected again on a different column. So I did what any stubborn person does at 11pm: I started submitting files one at a time through the web form, and somewhere around item twelve I could not remember whether I had already uploaded item seven. That was the moment the whole pipeline stopped being about making art and started being about finishing it.
The four jobs that actually stall people
Making the art is the fun part. The four things that stall people are metadata, double posting, turning a doc into a product, and packaging. Those are exactly the four jobs four standalone Python scripts handle in this project: make_metadata.py, upload_tracker.py, md2pdf.py, and pack_product.py. No framework, no cloud account. Only two third party packages exist in the whole set, Pillow for covers and reportlab for PDF output. The other two scripts run on the standard library alone, so you can skip the install entirely if metadata and tracking are all you need.
Metadata: the CSV header is the whole game
All three channels reject a wrong CSV header instantly, and each one wants a different shape. Adobe takes a 5 column CSV, Vecteezy takes 4 columns, Dreamstime takes 15. Writing those by hand once is fine. Writing them for a batch, then again for the next batch, is how mistakes get in. make_metadata.py writes the header the channel demands and nothing else:
python make_metadata.py ./my-assets --platform adobe --out metadata.csv --ext .jpg
python make_metadata.py ./my-assets --platform vecteezy --out vecteezy.csv --ext .jpg
python make_metadata.py ./my-assets --platform dreamstime --out dreamstime.csv --ext .jpg
Without a titles file it title cases the filename and uses that as the title. That is fine for a first pass and wrong for submission. Pass --titles titles.json with real titles and keywords before you upload anything.
Tracking: the re-run is the real danger
The fastest way to get an account flagged is running your batch twice, and batch scripts invite exactly that. You fix one file, you rerun, and now half your catalogue is posted in duplicate. upload_tracker.py is a plain ledger of what you have already posted:
python upload_tracker.py pending items.txt
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py status
Nothing clever, which is why it works. If a filename is not in the ledger, it shows up as pending. If it is, it does not.
Docs and packaging: make it look like a product
You have the content and you need it to look like something people pay for. md2pdf.py content.md product.pdf "My Product Title" turns a Markdown file, headings, tables, lists, links and all, into a styled PDF in one command. Then pack_product.py my-product "My Product" "A short subtitle" 9 writes a zip, a 1280 by 720 cover, and a 600 by 600 thumbnail into a _system folder. A zip with a real cover sells. A bare file does not.
The folder rules and the tiny server
The four scripts ran against a folder layout that keeps a catalogue from turning into a junk drawer: assets/ for raw output, output/ for ready to submit files plus the CSV, packs/ for finished zips and covers, research/ for notes and sources, scripts/ for the tools. Keep research/ forever. Deleting scrape logs to clean up is a mistake this project made once and will not repeat.
All of this ran on 1 vCPU, 2 GB of RAM, and no GPU. It works because of habits, not hardware: one process at a time, never fan out image jobs on a single core box, call gc.collect() after each asset, measure peak RSS with resource.getrusage(RUSAGE_SELF).ru_maxrss instead of average memory, run heavy renders in one subprocess per file so memory goes back to the OS, and render previews at 60 dpi instead of 300.
To put a number on the scale: these exact scripts packaged 39 products and 856 MB of output, sitting underneath roughly 19,000 lines of pipeline code and more than 300 pages of research that produced the rules the scripts enforce. The four tools are the small visible part. The rules behind them are why the headers are right the first time.
Honest note on where this came from
I did not write these four scripts to publish a tutorial. I wrote them because the web form broke me at item twelve. Everything in this post comes from a working pipeline that has already shipped a catalogue, and the four scripts are the version I wish I had on that first night: one folder in, three CSVs and a zip out, no double posts.
If you want the working tools rather than a sketch of them, they are packaged as part of a kit built from this exact project.
Building digital products? Free guides & kits for digital product sellers.
Top comments (0)