Last February I lost a whole evening to a CSV header. I had 40 finished JPEGs ready for Adobe Stock, generated the metadata file, uploaded it, and got an instant rejection. Not a warning, not a partial accept. Rejected. The problem was one column: Adobe's upload CSV wants exactly five columns in a specific order, and I had six. A single extra field, probably a trailing keyword I thought was helpful, and the whole batch was dead on arrival.
That night I rewrote the metadata step as a script that writes the header the platform demands and nothing else. It became the first of four tools that now package every product I sell. This post is about why those tools need exactly two third-party dependencies, and why I think that number matters more than people realize.
The four things that actually stall you
Making the art is the fun part. What stalls solo makers is everything after it. In my case it was four specific things:
- Metadata. Adobe wants a 5-column CSV, Vecteezy wants 4 columns, Dreamstime wants 15. Get the header wrong and the upload is rejected before a human ever sees your work.
- Double-posting. Run your batch script twice, as I did once, and you can post the same asset twice. That is one of the fastest ways to get an account flagged. I now keep a ledger script that remembers what is done, so a re-run is impossible.
- Turning a document into a product. You have the content, but a raw Markdown file does not look like something anyone would pay for.
- Packaging. A zip with a real cover image sells. A bare file does not.
My solution for all four is four standalone Python scripts. No framework, no cloud account, no database server.
Why only two dependencies
Here is the full list of third-party packages across all four scripts: Pillow and reportlab. That is it.
Pillow renders the product covers (1280 by 720) and thumbnails (600 by 600). reportlab turns Markdown into a clean styled PDF with headings, tables, lists, and links. The other two scripts, the metadata builder and the upload tracker, use the Python standard library alone. If you only need those two, you install nothing at all.
I did not set out with a minimalism goal. It fell out of running this on a small server. The whole pipeline runs on 1 vCPU and 2 GB RAM with no GPU. Every dependency you add is memory you do not have, a version conflict you will eventually debug at midnight, and a supply chain surface you have to think about. Pillow and reportlab are both mature, both do exactly one job well, and both fit comfortably in 2 GB when you use them one file at a time.
The practical rule I landed on: if the standard library can do it with under about fifty lines of code, write the fifty lines. CSV writing, file tracking, zip creation, all of that is built in. Only reach for a package when the job genuinely needs it, like image rendering or PDF layout.
The small server habits that make it work
Two dependencies do not help if your process eats the box. These habits are what let the pipeline run on that 1-core machine:
- One process at a time. Never fan out image jobs in parallel on a single core. It does not go faster, it just swaps.
- Call
gc.collect()after each asset. Freeing memory between items keeps peak usage flat instead of climbing. - Measure peak RSS, not average.
resource.getrusage(RUSAGE_SELF).ru_maxrssgives you the real ceiling. Average memory lies. - Run heavy render steps as one file per subprocess, so memory is actually returned to the OS when the file finishes.
- Render at the resolution you need. Inspecting a preview at 60 dpi instead of 300 is the difference between fitting in RAM and not.
For scale reference: these scripts packaged 39 finished products, 856 MB of output, as part of a parent project with around 19,000 lines of pipeline code. The rules behind them came from 300+ pages of research into what the stock platforms actually accept and reject.
The folder structure that keeps a catalogue sane
One structural decision saved me more time than any script: a fixed layout for every project.
project/
assets/ raw output, one file per asset
output/ ready-to-submit files plus metadata.csv
packs/ finished product zips plus covers
research/ notes and sources
scripts/ the tools
The one I got wrong early: keep research/ forever. I deleted scrape logs and notes once to clean up, then needed them two months later for a follow-up product and had to redo the work. Your research folder is raw material for future products. It is not clutter.
Where the tooling lives now
Those four scripts, make_metadata.py, upload_tracker.py, md2pdf.py, and pack_product.py, are the packaging layer of everything I sell. They are collected, documented, and shipped as part of the ai sticker factory playbook, which is the honest writeup of this whole system: the prompt side, the platform rules, the RAM constraints, and the packaging scripts, all validated on that same 1 vCPU, 2 GB box. If you want the same pipeline without rediscovering the CSV header rules the hard way, that is where it is.
Get ai sticker factory playbook
Building digital products? Free guides & kits for digital product sellers.
Top comments (0)