One background image plus a CSV, and you get one personalised image per row, zipped, with a manifest CSV that lists every filename. Free, no signup, and no file is uploaded anywhere.
Load a background image in step 1 and the preview will appear here.
Anywhere the same picture needs a different name on it. Fifty course certificates as PNGs for a Slack drop. Fifty client named social posts from one branded template. A mockup per prospect for a portfolio push. Ticket art with an attendee name. Conference badges. Every one of those is the same job: take one design, loop a spreadsheet, write a different value into the same spot each time, and end up with a folder of files.
Every layer is placed with a nine point grid plus a nudge slider, and every measurement is stored as a share of the background rather than as pixels. That is the difference between a preview that matches the export and one that does not. Change the output size from 1200 px to full resolution and the text stays exactly where you put it, at the same relative size, because nothing in the layout is tied to the size of the preview on screen.
A folder of images on its own is only half of a campaign. The ZIP also contains manifest.csv, which holds the rows you actually ran with an image_filename column added, and an image_url column when you give a base URL. Upload the images, then feed that manifest to your sending tool and each contact already points at their own picture. Without it you are matching rows to files by hand. A list run in blocks gives you one manifest per block, so stack them before importing.
System fonts only, so the four choices here render the same way in the export as they do in the preview with no font loading step to go wrong. Up to 200 rows in one run, because the archive is assembled in memory before it is handed to you. And it produces files, not hosting: the images still need to live at a public address before an email client can show them.
The background, the logos and the CSV are read by the page and drawn on a canvas in your own browser. No file you choose is ever sent anywhere. The page does make requests of its own, so here they are in full: it loads two open source libraries, JSZip and Papa Parse, from a public CDN when it opens, and it sends an anonymous page view plus a count of how many images a run produced to Castwright's own analytics. Nothing from your background, your logos or your CSV goes into either one.