DEV Community

Cover image for Running 39 Products Through Adobe, Vecteezy And Dreamstime Without Spending On Cloud

Running 39 Products Through Adobe, Vecteezy And Dreamstime Without Spending On Cloud

Last March I lost a full Saturday to a CSV header.

I had 40 vector files ready to upload to Adobe Stock. I built the metadata CSV by hand, guessed at the column order, uploaded the batch, and got rejections within the hour. Adobe's uploader checks the header row before it looks at a single file. Five columns, in their exact order. Mine had the right data in the wrong positions, so all 40 uploads failed before review even started. That was the moment I stopped hand-editing CSVs and wrote a script that writes the header the platform demands and nothing else.

Since then the pipeline has packaged 39 finished products, about 856 MB of output, running on a server with 1 vCPU, 2 GB RAM and no GPU. No cloud account, no monthly bill. Here is what actually works.

The metadata headers are the gate, not the review

All three major channels reject a wrong CSV instantly, before any human or AI review sees your work. Adobe wants a 5-column header. Vecteezy wants 4 columns. Dreamstime wants 15. If you get the column count or order wrong, the upload dies at the door.

So the first rule of my pipeline: never type a header by hand. make_metadata.py reads a folder of files and emits the exact CSV for whichever platform you name. It uses only the Python standard library, so there is nothing to install. You can pass a titles.json if you have real titles and keywords, or let it title-case the filenames for a first pass. Just replace those filename titles before you submit, reviewers notice keyword stuffing and generic titles fast.

The point is not that this is clever. The point is that metadata is mechanical, and mechanical work should be a script, not your evening.

Double-posting is the fastest way to get flagged

The second time I ran a batch, I did it on purpose to test, and I immediately understood why the tracker exists. Running your upload batch twice, even accidentally, is the kind of behavior that gets an account flagged. When you have 39 products across three platforms and you re-run a script at 1 a.m. you will not remember what already went out.

upload_tracker.py is a tiny ledger. pending shows what is not done yet, done marks an item, status gives the overview. It is also standard-library only. The whole script exists to make one mistake impossible, and that is a good use of 80 lines of code.

The packaging layer is where products actually get made

Making the art is the fun part. What stalls people, in my experience and in the mail I get, is the four steps after:

  1. Metadata, covered above.
  2. Double-posting, covered above.
  3. Turning a document into something that looks like a product.
  4. Bundling files with a cover that sells.

For step 3, md2pdf.py turns a Markdown file into a styled PDF with working headings, tables, lists and links. It uses reportlab, one of exactly two third-party packages in the whole kit. One command: input, output, title.

For step 4, pack_product.py zips the files and renders a 1280×720 cover and a 600×600 thumbnail. A zip with a real cover sells. A bare file does not, and I have the sales numbers to prove it on my own catalogue. The renders use Pillow, the second third-party package. If you only need the metadata and tracker scripts, you can skip installing anything at all.

How this runs on 2 GB of RAM

The whole pipeline runs on a 1-core box, and it works because of habits, not hardware:

  • One process at a time. Never fan out image jobs in parallel on a single core. You gain nothing and you OOM.
  • Call gc.collect() after each asset. Free memory between items or the peak creeps up batch after batch.
  • Measure peak RSS, not average. resource.getrusage(RUSAGE_SELF).ru_maxrss tells you the real ceiling. Average memory lies.
  • Run heavy render steps one file per subprocess, so the OS actually gets the memory back.
  • Render at the resolution you need. Inspecting a preview at 60 dpi instead of 300 cuts memory and time by a large factor, and you only need 300 dpi for the final file.

The same discipline applies to AI image generation costs. Generate at the resolution you need for review, upscale only the keepers. On a hobby budget, wasted renders are the biggest silent cost.

Keep your research folder forever

One structural thing that sounds trivial. The layout this pipeline assumes is fixed: assets/ for raw output, output/ for submission-ready files plus CSVs, packs/ for finished zips and covers, research/ for notes and sources, scripts/ for the tools.

I once deleted research/ to "clean up" and lost the raw material for three products I had planned. The scrape logs and notes behind one product are the seed for the next two. The 300+ pages of research behind the rules in these scripts exist only because I stopped deleting things. About 19,000 lines of pipeline code sit on top of that research, and the four scripts here are the packaging layer you can actually reuse.

Where to get the tools

Everything above is in the Pipeline Starter Kit: the four scripts, the folder layout, the RAM notes, and the quick-start commands. No framework, no cloud account, two pip packages, validated on 1 vCPU and 2 GB RAM. It is the tool I built out of this work, sold at a maker price because that is who it is for. If you just want the metadata headers fixed and the double-post problem gone, the two standard-library scripts alone are worth it.

See the kit


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

Top comments (0)