Generating portal images
core.generate_image is a utility on the core object that renders a branded
PNG for a Cloudpath tenant-property portal or management portal. It runs a small
image pipeline inside the Worker and hands the PNG bytes back to your code as
base64, so you can upload them through core.call in the same code_mode
invocation — the bytes never round-trip the MCP transport.
Four targets, two upload paths
Section titled “Four targets, two upload paths”Each target maps 1:1 to a Cloudpath upload endpoint. Logos are 4:1 banners; favicons are square monogram tiles.
| Target | Size | Uploads to |
|---|---|---|
tenant_logo | 1024×256 | POST /properties/{guid}/uiConfiguration/logoFile |
tenant_favicon | 128×128 | POST /properties/{guid}/uiConfiguration/favicon |
mgmt_logo | 1024×256 | POST /mgmtPortals/{guid}/uiConfiguration/logoFile |
mgmt_favicon | 128×128 | POST /mgmtPortals/{guid}/uiConfiguration/favicon |
Logos combine an AI-generated background (Workers AI,
@cf/black-forest-labs/flux-1-schnell) with a typography overlay. Favicons skip
the AI step entirely and render a pure monogram tile.
Parameters
Section titled “Parameters”| Parameter | Required for | Notes |
|---|---|---|
target | all | One of the four targets above |
primaryText | logo targets | The main line of text |
backgroundPrompt | logo targets | Subject and mood for the AI background |
monogram | favicon targets | 1–2 characters |
primaryColor | all | Hex, e.g. #0D2B45 |
accentColor | all | Hex |
secondaryText | optional | Second line on logos |
textColor | optional | Hex, default #FFFFFF |
font | optional | inter (default), playfair, montserrat, dm-serif |
layout | optional | left-gradient, center-vignette, bottom-bar (defaults: left-gradient for logos, center-vignette for favicons) |
Return shape
Section titled “Return shape”{ imageBase64, mimeType, width, height, suggestedFilename, model, aiGenerationMs, overlayMs }model is the Workers AI model used, or null for favicons (which make no AI
call). suggestedFilename is the value to use in the multipart upload’s text
field — see below.
Uploading the image
Section titled “Uploading the image”The four uiConfiguration upload endpoints expect multipart/form-data, and
uploading them has two gotchas that will silently corrupt the result if missed:
Second, because the isolate marshals tool arguments through JSON.stringify,
you cannot pass a Uint8Array, FormData, or Blob as body — assemble the
multipart body yourself, base64-encode it, and pass it as bodyBase64 with the
Content-Type (including the boundary) set in headers. See
Calling conventions.
// Generate + upload a property portal logo in a single code_mode call.async () => { const img = await core.generate_image({ target: 'tenant_logo', primaryText: 'HARBORVIEW RESIDENCES', backgroundPrompt: 'aerial view of a luxury waterfront community at golden hour', primaryColor: '#0D2B45', accentColor: '#C8960C', font: 'playfair', });
// Decode the returned PNG bytes. const bin = atob(img.imageBase64); const png = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) png[i] = bin.charCodeAt(i);
// Build the multipart body: a `filename` text part + the `file` image part. const boundary = '----cp-mcp-' + Math.random().toString(36).slice(2); const enc = new TextEncoder(); const head = enc.encode( `--${boundary}\r\nContent-Disposition: form-data; name="filename"\r\n\r\n${img.suggestedFilename}\r\n` + `--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="${img.suggestedFilename}"\r\nContent-Type: image/png\r\n\r\n` ); const tail = enc.encode(`\r\n--${boundary}--\r\n`); const body = new Uint8Array(head.length + png.length + tail.length); body.set(head, 0); body.set(png, head.length); body.set(tail, head.length + png.length);
// Base64-encode in chunks (spread would overflow the call stack), one btoa at the end. let s = ''; for (let i = 0; i < body.length; i += 0x8000) { const sub = body.subarray(i, i + 0x8000); for (let j = 0; j < sub.length; j++) s += String.fromCharCode(sub[j]); }
const r = await core.call({ method: 'POST', path: '/properties/{guid}/uiConfiguration/logoFile', pathParams: { guid: 'your-property-guid' }, headers: { 'Content-Type': `multipart/form-data; boundary=${boundary}` }, bodyBase64: btoa(s), }); return { uploaded: r.ok, status: r.status, model: img.model };}