DEV Community

Cover image for # 3 dev.to Article Titles

# 3 dev.to Article Titles

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Metadata, solved above.
  2. Double-posting, solved above.
  3. 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.py does it in one command, using reportlab, one of only two third-party packages in the whole kit.
  4. Packaging. A zip with a real cover sells. A bare file does not. pack_product.py bundles 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Get digital asset factory


Building digital products? Free guides & kits for digital product sellers.

Top comments (0)