3 dev.to Article Titles
Wait, no. This post is not a listicle about titles. It is the post about the moment my upload batch got rejected twice in one morning, and the four scripts I wrote so it never happens again. The title above is what I almost published instead, and deleting it taught me more than writing it did.
Here is the real story.
The morning Adobe rejected 40 CSVs
Last spring I had 40 finished JPGs sitting in a folder, ready to go. I built the upload CSV by hand in a spreadsheet, exported it, uploaded it, and got an instant rejection. Wrong column count. Adobe wants 5 columns. I fixed it, re-exported, tried Vecteezy, and got rejected again because Vecteezy wants 4 columns, not 5. Dreamstime wants 15. Three platforms, three headers, and every one of them rejects the file instantly without telling you which column is wrong.
That was the moment I stopped hand-building CSVs and wrote make_metadata.py. It writes the exact header each platform demands and nothing else. One command per platform:
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
Without a titles file it title-cases the filename, which is fine for a first pass but you should replace it before submitting. The point is the header is never wrong again.
The second rejection was worse: double-posting
Two weeks later I re-ran a batch script, forgot I had already submitted half of it, and double-posted. Duplicate submissions are one of the fastest ways to get a stock account flagged. Nothing about the rejection message says that, you just notice your acceptance rate drop.
So I wrote upload_tracker.py, a plain ledger that remembers what is done:
python upload_tracker.py pending items.txt
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py status
A re-run can no longer double-post because the tracker makes it impossible, not just unlikely. This uses the Python standard library alone, no install at all.
The packaging problem nobody warns you about
Making the art is the fun part. Selling it is four boring problems, and I hit all of them:
- Metadata, solved above.
- Double-posting, solved above.
- Turning a document into something that looks like a product. I had Markdown content and needed a clean PDF with headings, tables, lists, and links.
md2pdf.pydoes it in one command, using reportlab, one of only two third-party packages in the whole kit. - Packaging. A zip with a real cover sells. A bare file does not.
pack_product.pybundles the files and renders a cover at 1280x720 and a thumbnail at 600x600 using Pillow.
python pack_product.py my-product "My Product" "A short subtitle" 9
That writes the zip, the cover, and the thumb. Covers and thumbnails at the right dimensions matter because marketplace listings crop or reject anything else.
The tiny server habits that made it possible
This whole pipeline ran on 1 vCPU, 2 GB RAM, no GPU. It works because of habits, not hardware:
- One process at a time. Never fan out image jobs in parallel on a 1-core box.
- Call
gc.collect()after each asset. - Measure peak RSS with
resource.getrusage(RUSAGE_SELF).ru_maxrss, not average memory. Average lies, the ceiling is what kills you. - One file per subprocess for heavy render steps so memory returns to the OS.
- Inspect previews at 60 dpi, render at 300 only when it is final.
AI image generation costs add up fast when you regenerate because of a packaging mistake, so getting packaging right the first time is also a cost decision.
The folder layout that saved me from a junk drawer
project/
assets/ raw output, one file per asset
output/ ready-to-submit files + metadata.csv
packs/ finished zips + covers
research/ notes and sources
scripts/ the tools
Keep research/ forever. I deleted mine once to "clean up" and lost the raw material for three future products. I will not repeat that.
Where this stands now
The kit contains the exact scripts that packaged 39 products, about 856 MB of output, from a parent project with roughly 19,000 lines of pipeline code and 300+ pages of research behind the rules the scripts enforce. So far 1,860 assets have gone through the pipeline and 1,077 are ready or submitted. The first paid sale from this whole system was $2.80, and it was for the system itself, the Digital Asset Factory. I am not going to pretend that number is anything but a start. But it is real money from a pipeline that runs on a 2 GB server, and every part of it is documented.
The Digital Asset Factory is the full system built from this work, the four scripts here are just the packaging layer, sitting under a free orchestration stack. If you want the whole thing instead of the four tools, that is where it lives.
Building digital products? Free guides & kits for digital product sellers.
Top comments (0)