The 1280×720 Lesson: Why a Zip Isn't Shippable Until It Has a Cover
I'll never forget uploading my eighth product, waiting a day, and seeing this: zero previews. The zip was fine. The files inside were fine. I'd spent hours on the art. Nobody clicked. The listing had no cover, just a generic download icon, and in a marketplace grid that icon is invisible next to everything else. That was the day a zip stopped being a "product" to me and became a component. A product is the zip plus the cover. I've since packaged 39 products, 856 MB of output in total, and every single one ships with a cover rendered at exactly 1280×720 plus a thumbnail at 600×600.
Here's what I learned about getting that last 5 percent right.
Why the cover, not the zip, is the product
I run a fixed packager now. It is a single script called pack_product.py, and it does one thing: it zips the files and renders the cover and the thumbnail in the same operation. The signature looks like this:
python pack_product.py my-product "My Product" "A short subtitle" 9
That 9 is the color seed for the gradient background. The script writes my-product.zip, my-product-cover.jpg (1280×720) and my-product-thumb.jpg (600×600) into a _system folder next to where you run it. The cover and the zip are created together. They can never drift apart, because I made them one step. That is the whole trick: make the cover impossible to skip by fusing it to the thing you cannot forget.
On a stock marketplace grid, 1280×720 is the ratio most preview panes are built around. It gives you enough horizontal room for a title and a visual hint of what is inside. The 600×600 thumbnail is what the search results show first. If that one is illegible at the size of a postage stamp, your cover never gets seen. Two sizes, two jobs.
The zip alone fails on nearly every channel
I built a metadata generator for the three channels I actually publish to, and the difference between them is not subtle:
- Adobe Stock wants a 5-column CSV
- Vecteezy wants a 4-column CSV
- Dreamstime wants a 15-column CSV
Get one header wrong and the file is rejected instantly. The script, make_metadata.py, writes the exact header each platform demands and nothing else. It runs like this:
python make_metadata.py ./my-assets --platform adobe --out metadata.csv --ext .jpg
If you pass --titles titles.json you get real titles and keywords. Without it, the filename gets title-cased and used as a placeholder. That is fine for a first pass. It is not fine to submit. Replace it before you upload.
My point is that none of this matters if the listing behind the CSV has an invisible preview. The cover is the rate-limiter on every channel. You can have the perfect 15-column Dreamstime file and still sell nothing.
Double-posting is the real account killer
The fastest way to get an account flagged is running your batch twice. I built upload_tracker.py to make that mechanically impossible:
python upload_tracker.py pending items.txt # what is NOT done yet
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py status
There is no clever reasoning here, just a ledger. It remembers what you posted. That is enough.
The kit runs on a potato, and that is the point
All of this ran on 1 vCPU, 2 GB RAM, no GPU. That is not a flex, it's a constraint that shaped the design. Five habits keep it alive:
- One process at a time. Never fan out image jobs on a 1-core machine.
-
Free memory between items. Call
gc.collect()after each asset. -
Measure peak RSS, not average.
resource.getrusage(RUSAGE_SELF).ru_maxrsstells you the real ceiling. - One file per subprocess for heavy render steps, so memory goes back to the OS.
- Render at the resolution you need. A preview at 60 dpi beats a full render at 300.
The cover renderer uses Pillow. That is one of only two third-party dependencies in the whole kit. The other is reportlab, used by md2pdf.py to turn a Markdown file into a clean PDF:
python md2pdf.py content.md product.pdf "My Product Title"
make_metadata.py and upload_tracker.py need nothing but Python, no install at all. If that's all you use, skip the virtualenv entirely.
The folder layout that saves you later
A catalogue turns into a junk drawer without a fixed structure. This is the layout the kit assumes:
project/
assets/ raw output, one file per asset
output/ ready-to-submit files + metadata.csv
packs/ finished product zips + covers
research/ notes and sources
scripts/ these tools
Keep research/ forever. Your scrape logs and notes are the raw material for the next product. I deleted mine once to "clean up" and I will not do it again. The four things that actually stall a solo maker are metadata, double-posting, turning a doc into a product, and packaging. The kit covers all four. What it does not do is decide what to make.
What actually shipped
Behind these scripts sits roughly 19,000 lines of pipeline code in the parent project and 300+ pages of research that produced the rules the scripts enforce. The four packaging tools are the last mile of that work, and the 1280×720 cover is the last inch.
If you want the whole method, not just the four scripts, the ai sticker factory playbook is where I collected it: the pipeline, the platform rules, the RAM habits, and the cover templates that ended the zero-preview problem for good. It is the tool built from every mistake described above.
Get ai sticker factory playbook
Building digital products? Free guides & kits for digital product sellers.
Top comments (0)