Image models are genuinely good now. Ask Nano Banana — Google's Gemini image model — or GPT Image for a blog hero, a diagram, or a social card, and you get something you'd actually ship. Then the model hands you a link that expires in about an hour (OpenAI's image URLs do exactly this), or a base64 blob that's expensive to carry around and clumsy to save. The picture is great; it has nowhere durable to live.
So you break out of the flow: download the file, open a browser, drag it into a CMS or a GitHub issue, copy the URL back. Your coding agent generated the image in seconds; you spend the next ten minutes playing courier for it. That last mile — from "here's a nice image" to a URL you can embed — is the whole problem, and it's exactly where hosting AI-generated images usually falls down.
The loop, closed
Give the agent one more tool — image hosting that returns a permanent URL — and generate-and-host runs end to end without you:
- Generate. The agent calls an image model — GPT Image, or Google's Nano Banana (
gemini-3.1-flash-image) / Nano Banana Pro (gemini-3-pro-image) — for the hero and any inline art. - Host. It hands the result to PixelVault and gets back
https://img.pixelvault.dev/…, a permanent, globally-cached URL that won't rot. - Embed. It drops that URL into the Markdown and the
og:imagetag, and moves on — and yes, it can write the surrounding post too.
No context switch, no browser, no manual upload. The hero at the top of this post was made exactly this way — Nano Banana → PixelVault, one command.
The prompt lives in version control
Image models are non-deterministic — run the same prompt twice and you get two different pictures. So the trick to making this repeatable is to treat the prompt as source. We keep a tiny manifest, one entry per post, with the prompt, the alt text, and the URL the tooling fills in:
// so the art is reproducible and the URL is filled in for you.
{
"nano-banana-image-hosting": {
"prompt": "Editorial blog hero, flat vector... no text. 16:9.",
"alt": "A coding agent generating an image with Nano Banana and hosting it on PixelVault",
"url": ""
}
}
Now regenerating art is one command, and anyone — human or agent — can reproduce or tweak a hero without hunting for the original prompt:
npm run gen-hero -- nano-banana-image-hosting
# → hosted, and the permanent URL is written back into the manifest:
# https://img.pixelvault.dev/<project>/<image>.png
The open-source skill that does it
Behind that command is a small, open-source skill — pixelvault-generate — that does one thing: take a prompt, generate the image through OpenRouter (point it at whichever image model you like), then host the result on PixelVault and hand back the permanent URL. It's a SKILL.md plus a few lines of shell, so any agent that reads a skill file can run it — and it drops into any project. The hero on this page was made exactly this way with google/gemini-3.1-flash-image; swap the slug for google/gemini-3-pro-image and you're on Nano Banana Pro instead.
If your agent already speaks MCP, it doesn't even need the script — PixelVault's upload_image tool takes a source_url, so the agent can hand it the model's temporary link and get a permanent one back directly. Either way, the instruction to the agent is a single rule you drop in your repo:
When a post needs a hero, add a prompt to heroes.json,
run `npm run gen-hero -- <slug>`, then reference the hosted URL.
Never paste base64 or a temporary model URL into a post.
One upload, every size
A hero image needs to be several things at once: a crisp picture in the article, a 1200×630 card for social previews, a lightweight thumbnail in a list. You don't generate those separately. PixelVault does transforms from the URL, so one upload becomes every size by adding query params — ?w=1200&h=630&fmt=auto for the OG card, ?w=700&fmt=auto&q=auto for the body. The original PNG on this post is over a megabyte; the card your social feed actually loads is a 73 KB JPEG, chosen automatically. The agent uploads once; the sizes take care of themselves.
Where the keys live
Image generation is an authoring-time job, not something your deployed site does. The OpenRouter key and your PixelVault key sit in a local .env the tooling reads when you run the command — they never ship to production, and the published page only ever references the finished img.pixelvault.dev URL. Your build stays fast, deterministic, and secret-free.
A note on ownership — and what's next
Right now your images live in PixelVault's storage on Cloudflare's edge, served from a zero-egress CDN, so a post that goes viral doesn't hand you a bandwidth bill. Bring-your-own-key (BYOK) is coming with the paid plans — alongside custom domains and unlimited private links — so you can point PixelVault at your own R2 or S3 bucket, own the bytes, and keep the same one-call hosting and transforms. It's on the roadmap, not shipped yet; we'll say so plainly here when it lands.
Try the loop
Give your agent a hosting tool and the courier work disappears. Grab a key by registering with a single API call, connect the MCP server or drop in the skill, and the next post your agent writes can illustrate and publish itself. The free tier includes 200 MB storage, 500 uploads/month, and 1 GB bandwidth — no credit card. Paid plans start at $9/month.