DEV Community

Cover image for The 1280 720 Lesson: Why a Zip Isn't Shippable Until It Has a Cover"**

The 1280 720 Lesson: Why a Zip Isn't Shippable Until It Has a Cover"**

The 1280×720 Lesson: Why a Zip Isn't Shippable Until It Has a Cover

I zipped my first product and uploaded it. Then I looked at it in the store back end and felt something drop in my stomach. It was a bare archive. No cover, no thumbnail, no image on the listing at all. Just a title, a price, and an empty gray box where every competitor had a picture.

The files inside were fine. That was the problem. The work was finished and the product still wasn't sellable. I pulled the listing, spent a night making a 1280×720 cover by hand, and learned the rule that now lives in my pipeline: packaging fails last and it fails quietly, so the pack step has to happen on every product, every time, automatically.

Here is what actually works, with the numbers from my own register.

The rule that stopped the broken listings

The fix was pack_product.py, one script that does three things in a single run: zips the files, renders a 1280×720 cover, and renders a 600×600 thumbnail. The cover is the listing image. The thumbnail is the small preview. Neither is optional.

That order matters. Build the zip first, then the images from the same run, so the three artifacts can never drift apart. If I edit a product, I repack, and all three outputs are regenerated together. No product leaves the folder without a cover, because there is no step where a zip exists alone.

This is boring and that is the point. Packaging should have no decisions in it.

Metadata fails before the buyer ever sees the files

The cover problem was visible. The metadata problem is worse because it is invisible until a rejection email arrives.

All three channels I publish to check the CSV header before they read anything else, and a wrong header means instant rejection. Each channel wants a different shape. I build three separate files from the same asset folder:

  • Adobe: a 5 column CSV
  • Vecteezy: a 4 column CSV
  • Dreamstime: a 15 column CSV

make_metadata.py writes exactly the header each one demands and nothing else. Run it once per channel against the same folder and you get three CSVs that match three different upload forms. Without the --titles flag it title-cases the filename, which is fine for a first pass. Replace the titles before you submit. The script gets you to the gate; it doesn't lie to you about being done.

The fastest way to get flagged is running your batch twice

While building this out I nearly double-posted a batch. The second run went through before I caught it. Nothing happened that time, but the register is clear that the fastest way to get an account flagged is posting the same file twice, and I did not want to find out how the platforms feel about it.

upload_tracker.py is a ledger. Before a batch, ask it what's pending. After each upload, mark the item done. A re-run can't repost what it already knows is posted.

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

The habit is the product here. One file remembers what you already did, so a retry after a crash is safe instead of risky.

It all ran on 1 vCPU and 2 GB of RAM

The whole pipeline, all 39 products and 856 MB of output, ran on a single core server with no GPU. That only works because of a few rules I keep:

  • One process at a time. Never fan out image jobs in parallel on one core.
  • Free memory between items. gc.collect() after each asset.
  • Measure peak, not average. resource.getrusage(RUSAGE_SELF).ru_maxrss tells you the real ceiling, and the average will lie to you.
  • One file per subprocess for heavy render steps, so memory goes back to the OS.
  • Render at the size you need. Previewing at 60 dpi beats rendering at 300.

None of this is clever. It is what lets a hobby server finish a batch without dying at item 30.

The folder layout that keeps a catalogue from turning into a junk drawer

Every product follows the same structure: assets/ for raw output, output/ for ready files and the metadata CSV, packs/ for finished zips and covers, research/ for notes, scripts/ for the tools. One rule I will not break again: keep research/ forever. I deleted scrape logs once to clean up, and lost the raw material for the products that came next.

The cover lesson generalizes. A catalogue isn't finished when the art is done. It's finished when every item has a cover, a clean metadata row, and a note in the ledger saying it went out. Those three things are the difference between a folder of files and a shippable product line.

The product is called digital asset factory. It is the kit built directly from this work: the four scripts above (packaging, metadata, tracking, and Markdown to PDF), the folder rules, and the constraints from running it all on 1 vCPU with 2 GB of RAM. It came out of 39 packaged products, around 19,000 lines of pipeline code in the parent project, and 300+ pages of research behind the rules the scripts enforce.

Get digital asset factory


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

Top comments (0)