Short answer: generate the PNG inside the Next.js API route, write it under a new key in private object storage, and return that key plus an expiring signed download link; keep the browser away from storage credentials, and choose a different service if the image must have a permanent public URL.
This is an ownership boundary, not a framework trick. The route owns generation and persistence, while the browser receives a disposable capability to view or download one object. For a US/EU SaaS deployment, select the storage region from server-side tenant policy before generation starts, record the chosen region with the object key, and make that policy part of the same review as data residency. Don't let a client-supplied bucket quietly become the residency control.
The operational target should be equally blunt: a successful API response means the bytes were accepted and a signed link was created. Anything less is failure, even if image generation succeeded.…