From b7d96e67883b89475f8fc4160a88e05f7da3b67f Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 11:28:49 +0000 Subject: [PATCH 1/6] Add cloudinary-image-picker skill (draft) Hackathon draft of a use-case skill that picks images for website slots from a Cloudinary product environment: discovers candidates (Visual Search, browse, or Search API on tags and captions), scores them, adapts near-misses with generative AI edits, generates new images when needed, and self-checks the rendered page. Marked internal while in progress. Co-Authored-By: Claude Opus 5.5 --- .../cloudinary-image-picker/SKILL.md | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 skills/use-cases/cloudinary-image-picker/SKILL.md diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md new file mode 100644 index 0000000..7988602 --- /dev/null +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -0,0 +1,347 @@ +--- +name: cloudinary-image-picker +description: "End-to-end recipe for choosing the right images for a website from a Cloudinary product environment, and generating new ones when nothing fits. Use when building a website or page that needs images, filling empty or placeholder image slots, replacing or refreshing existing site images (for example, a seasonal hero banner), or when the user asks to find, pick, match, or generate images for their site from Cloudinary." +license: MIT +metadata: + author: cloudinary + version: '0.1.0' + internal: true +--- + +# Cloudinary Image Picker + +Picks the best image for every image slot on a website from the assets in a Cloudinary product environment. It reads the page to understand what each slot needs, finds candidates with the best search method the product environment supports, looks at and scores them, adapts near-misses with generative AI edits, and generates a new image with the Image Generation API when no existing asset is close enough. Every chosen or generated image is delivered with transformations sized for its slot, then checked on the rendered page before handing back to the user. + +## When to Use + +- The user asks you to build a website or page, and the design includes images (hero banners, product cards, team photos, blog headers, backgrounds) +- An existing site has empty image slots, placeholder images (for example, `placehold.co`, `picsum.photos`, `via.placeholder.com`, gray boxes), or broken image links +- The user wants to replace or refresh existing images, for example, swapping a summer hero banner for an autumn one +- The user asks to find, match, or generate images for their site from their Cloudinary media library + +Don't use this skill for logos, icons, or brand marks: use the user's own files. For transformation syntax details, use cloudinary-transformations. For anything outside this skill's scope, use cloudinary-docs. + +## Prerequisites + +- **Credentials**: `CLOUDINARY_URL` (`cloudinary://:@`), or `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET`. Never print the secret or put it in client-side code. +- **Vision**: you must be able to view images (fetch an image URL and see its contents). Scoring depends on it. +- **Image Generation add-on** must be registered for the product environment to generate images. If it isn't, report the gap instead of generating. + +Optional, used when available (see [Choose a discovery method](#choose-a-discovery-method)): + +- **Visual Search**: Enterprise feature. The best way to search a large library by what images look like. +- **Cloudinary AI Content Analysis add-on**: auto-tagging and captioning, which make the Search API useful for finding images by content. Free tier available. +- **Cloudinary AI Vision add-on**: answers questions about an image, used to check shortlisted candidates. Free tier available. + +Every API call in this skill runs server-side (shell, script, or MCP tool). Only delivery URLs go into the site. + +## Workflow + +Copy this checklist and track progress: + +``` +- [ ] 1. Inventory image slots +- [ ] 2. Confirm scope with the user (if needed) +- [ ] 3. Write search queries per slot +- [ ] 4. Search and collect candidates +- [ ] 5. Score candidates and choose +- [ ] 6. Adapt near-miss images +- [ ] 7. Generate images for unfilled slots +- [ ] 8. Deliver with slot-sized transformations +- [ ] 9. Self-check the rendered page +- [ ] 10. Report to the user +``` + +### 1. Inventory image slots + +Before searching, build a slot list from the page code, the design, or your own plan for the site. For each slot, record: + +| Field | How to find it | +|---|---| +| `slot_id` | A short name, for example `home-hero`, `product-card-3` | +| Purpose | What the image does: sets a mood, shows a product, shows people, illustrates an article | +| Context | The heading, body text, and calls to action closest to the slot. This is the main signal for what the image should show. | +| Site context | Brand, audience, tone, color palette, season or campaign | +| Display size | Rendered width and height in CSS pixels at the largest breakpoint, from the CSS, the component props, or the layout | +| Aspect ratio | From the display size, or from `aspect-ratio`, `object-fit`, or fixed width and height | +| Minimum source size | Display size multiplied by 2 for high-density screens. For example, a 1440x600 hero needs a source of at least 2880x1200, or at least 1920 wide as a floor. | +| Overlay | Whether text or buttons sit on top of the image, and where. The image needs a calm, low-detail area there. | +| Current image | The existing URL, if any, and why it's being replaced | + +Read the copy closely and connect the dots. A section titled "Fresh from our kitchen" above a bakery menu needs warm, close-up food photography, not a generic "food" image. A "Meet the team" grid needs consistent head-and-shoulders portraits, not mixed group shots. + +### 2. Confirm scope with the user + +Ask one short, batched question only when the answer changes the search. Skip it when the user already said, or when the request is clearly open. Useful questions: + +- Limit the search to a folder, tag, or collection? (for example, only assets tagged `approved` or `CC0`) +- Any style preference: photography or illustration, people or no people, color mood? +- May you generate new images when nothing in the library fits, and save them to the product environment? + +If the user doesn't answer or says to go ahead, search all public images and generate where needed. + +### 3. Write search queries per slot + +Visual Search matches what an image *looks like*, so describe the picture, not the marketing message. + +- Use concrete nouns, setting, lighting, and composition: "close-up of a croissant on a wooden table, warm morning light", not "delicious bakery goodness" +- Include the orientation or framing the slot needs: "wide landscape view", "portrait of one person, head and shoulders", "product on a plain white background" +- Mention empty space when there's a text overlay: "with empty sky on the left" +- Write 2 or 3 query variants per slot, from specific to broad. The broad variant catches assets the specific one misses. + +Example for a `home-hero` slot above the heading "Autumn collection is here": + +1. `woman walking through a park with orange autumn leaves, wide shot, soft light` +2. `autumn leaves forest path, wide landscape` +3. `autumn fashion outdoor` + +### 4. Search and collect candidates + +#### Choose a discovery method + +Pick the first method that works for the product environment and the user's scope, and note which one you used for the report: + +| Method | Use when | Finds images by | +|---|---|---| +| A. Visual Search | A test call succeeds (Enterprise feature) | What they look like | +| B. Browse the scope | The scope (folder, tag, or whole library) holds about 100 images or fewer | Your own viewing of every image | +| C. Search API on tags and captions | The scope is larger, and assets have auto-tags or captions | Content keywords | +| D. Search API on existing tags and names | None of the above | Whatever keywords the uploader added | + +To test for Visual Search, run one visual search call. An error saying the feature isn't enabled means it's unavailable: move on without mentioning it again. To size the scope, run a Search API call with the scope expression and read `total_count`. + +#### A. Visual Search + +Run a [visual search](https://cloudinary.com/documentation/admin_api.md?install_source=skillspack&referrer=image-picker-skill#visual_search_for_resources) for each query variant: + +```bash +curl -s -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/resources/visual_search" \ + --data-urlencode "text=autumn leaves forest path, wide landscape" -G +``` + +```javascript +const res = await cloudinary.api.visual_search({ text: 'autumn leaves forest path, wide landscape' }); +``` + +Results come back ordered by relevance. Then: + +- **Apply the user's scope yourself.** Visual search takes only `text`, `image_url`, or `image_asset_id`, so filter the results on `tags`, `asset_folder`, or other returned fields after the call. Keep only `resource_type: image` and `access_mode: public`. +- **Page with `next_cursor`** if fewer than 5 candidates survive the filter, up to 3 pages per query. +- **Search by example** once you've found one good match: pass its `asset_id` as `image_asset_id` to find visually similar images. This keeps a page consistent, for example, all product cards with the same background style. + +#### B. Browse the scope + +When the scope is small, list it once with the [Search API](https://cloudinary.com/documentation/search_method.md?install_source=skillspack&referrer=image-picker-skill) and view every image yourself: + +```bash +curl -s -X POST "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/resources/search" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -H "Content-Type: application/json" \ + -d '{"expression": "resource_type:image AND tags:CC0", "max_results": 100, "with_field": ["tags", "context"]}' +``` + +- Drop images that are too small for every slot (`width` and `height` below the smallest slot's display size) before viewing. +- View each remaining image once as a small thumbnail (`c_limit,w_300/f_jpg/q_auto`) and write a one-line description of it. Reuse these descriptions for every slot instead of viewing the images again. +- Match descriptions against each slot's needs to build its shortlist. + +#### C. Search API on tags and captions + +Turn each query variant into keywords: the main subject, setting, and season (`autumn`, `forest`, `path`). Search with tokenized, prefix matching on tags and captions, combined with the user's scope: + +``` +resource_type:image AND tags:CC0 AND (tags:autumn* OR context.caption:autumn* OR tags:forest*) +``` + +Assets get content tags and captions from the [Cloudinary AI Content Analysis add-on](https://cloudinary.com/documentation/cloudinary_ai_content_analysis_automatic_tagging.md?install_source=skillspack&referrer=image-picker-skill). If the scope has no auto-tags or captions, offer the user a one-time pass. **Ask first**: it writes tags to their assets and uses add-on quota. For each asset, call the Admin API `update` method: + +- `detection=lvis` and `auto_tagging=0.6` to add tags for detected objects with 60% confidence or more +- `detection=captioning` to get a one-sentence caption. The caption comes back in `info.detection.captioning.data.caption`. Save it to the asset's `caption` context field so the Search API can match it. + +#### D. Search API on existing tags and names + +Search the keywords from method C against `tags`, `public_id`, `display_name`, and `context`. Results depend on how well uploaders labeled their assets, so expect weak results and more generation. + +#### For every method + +- **Merge and deduplicate** candidates across query variants by `asset_id`. Keep the best rank each one reached. +- Keep the top 5 to 8 candidates per slot for scoring. + +### 5. Score candidates and choose + +Read each candidate's `width`, `height`, `tags`, and `context` from the search results. Then **look at the image itself**: fetch a small preview such as `https://res.cloudinary.com//image/upload/c_limit,w_600/f_jpg/q_auto/` and view it. Never choose from the public ID, filename, or tags alone: they're often wrong or vague. + +Score every candidate against the slot: + +| Criterion | Weight | 0 | 1 | 2 | +|---|---|---|---|---| +| Subject match | 3 | Wrong subject | Related but generic | Shows exactly what the copy describes | +| Resolution | 2 | Below the display size | Between display size and the minimum source size | Meets the minimum source size | +| Crop fit | 2 | Key subject would be cut off at the slot's aspect ratio | Fits with a tight crop | Fits naturally, with room to spare | +| Composition | 1 | Busy or cluttered, or no calm area where an overlay needs one | Acceptable | Clear focal point, overlay area is clean | +| Tone and consistency | 1 | Clashes with the site's mood, palette, or the other chosen images | Neutral | Matches the mood and the other images on the page | +| Clean | 1 | Visible watermark, unrelated text, or third-party logos | Minor distractions | None | + +Maximum score: 20. Rules: + +- **Hard fails**: a 0 on subject match or resolution disqualifies the candidate, whatever its total. +- **Accept** the highest scorer if it reaches **14 or more**. +- **Don't reuse** one asset in two slots on the same page, unless the design intends it. +- **Check crop fit** by comparing aspect ratios: a 4:3 source in a 21:9 hero loses most of its height. `g_auto` helps, but can't add pixels that aren't there. +- If no candidate reaches 14, but one scores 10 or more and an edit could fix what it's missing, the slot goes to step 6. Otherwise, it goes to step 7. + +**Optional second opinion**: if the [Cloudinary AI Vision add-on](https://cloudinary.com/documentation/cloudinary_ai_vision_addon.md?install_source=skillspack&referrer=image-picker-skill) is available, use it to check slot-specific details on the top 2 or 3 candidates, for example, whether there's empty space for a headline. Ask yes-or-no questions with `ai_vision_general`: + +```bash +curl -s -X POST "https://api.cloudinary.com/v2/analysis/$CLOUDINARY_CLOUD_NAME/analyze/ai_vision_general" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "source": { "asset_id": "" }, + "prompts": ["Is the left third of this image plain enough to place a white headline over it? Answer yes or no, then give one reason."] + }' +``` + +Treat the answer as one input to your score, not a replacement for viewing the image. + +Record the score and a one-line reason for each choice. You need them for the report. + +### 6. Adapt near-miss images + +Editing an existing image is often better than generating a new one: it keeps a real photo, matches the rest of the library, and costs less. Consider it for: + +- A near-miss candidate from step 5 that has the right subject but one fixable problem +- The slot's current image, when you're replacing or refreshing it. For example, a summer hero can become an autumn one by changing its background or season, while keeping the same people and layout. + +Match the problem to the fix: + +| Problem | Fix | Example | +|---|---|---| +| Wrong aspect ratio, and cropping would cut the subject | Generative fill extends the image | `b_gen_fill,c_pad,ar_21:9,w_2000` | +| Unwanted object, person, or text | Generative remove | `e_gen_remove:prompt_(text;person)` | +| One object is wrong for the page | Generative replace | `e_gen_replace:from_coffee%20cup;to_pumpkin%20spice%20latte` | +| Wrong setting or season behind the subject | Generative background replace | `e_gen_background_replace:prompt_autumn%20park%20with%20orange%20leaves` | +| A product or item is the wrong color | Generative recolor | `e_gen_recolor:prompt_jacket;to-color_8B4513` | +| Low resolution or compression artifacts | Upscale, or generative restore | `e_upscale`, `e_gen_restore` | +| Several changes, or a restyle | The `image_to_image` endpoint, with the asset as the reference image | See below | + +Prompts inside a transformation URL must be URL-encoded (for example, spaces as `%20`). Use cloudinary-transformations for the exact syntax and limits of each [generative AI transformation](https://cloudinary.com/documentation/generative_ai_transformations.md?install_source=skillspack&referrer=image-picker-skill). + +For several changes or a restyle, use `image_to_image` with a temporary target, so you can check the result first: + +```bash +curl -s -X POST "https://api.cloudinary.com/v2/generate/$CLOUDINARY_CLOUD_NAME/image_to_image" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Keep the people and composition of [1], change the season to autumn with orange leaves and warm light", + "reference_images": [{ "source_type": "managed_asset", "asset_id": "" }], + "model": { "mode": "auto" }, + "target": { "target_type": "temporary" } + }' +``` + +Then: + +1. **Check the result**: open the transformation URL (the first request can take a while, since the edit runs then) or the `image_to_image` preview URL, and view it. Score it with the step 5 rubric. If it scores under 14, try a different fix or a clearer prompt, up to 2 attempts, then go to step 7. +2. **Save the approved result as a new asset**, using the same upload call as in step 7, with `tags=ai-edited,image-picker`. Don't overwrite the original. Saving also means the responsive sizes in step 8 resize one fixed image, instead of running the generative edit again for every width. + +### 7. Generate images for unfilled slots + +Use the [Image Generation API](https://cloudinary.com/documentation/image_generation_addon.md?install_source=skillspack&referrer=image-picker-skill) when no existing asset fits. If the user said not to generate, leave the best candidate in place and flag the slot in the report. + +**Write the prompt** from the slot inventory, not from the search query. A good prompt states: + +1. Subject and action: "a barista pouring latte art into a ceramic cup" +2. Setting and props: "on a marble counter in a small, sunlit cafe" +3. Style and medium: "editorial photography, shallow depth of field"; or "flat vector illustration" for illustrated sites +4. Lighting and palette, matched to the site: "warm golden morning light, cream and brown tones" +5. Composition for the slot: "wide 16:9 framing, subject on the right third, empty soft-focus space on the left for a headline" +6. Exclusions: "no text, no logos, no watermarks" + +Match the style of the images you already chose for the page, so the generated image doesn't stand out. + +**Generate a temporary preview first** so you can inspect it before saving anything: + +```bash +curl -s -X POST "https://api.cloudinary.com/v2/generate/$CLOUDINARY_CLOUD_NAME/text_to_image" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "", + "model": { "mode": "auto", "preference": "quality" }, + "image_size": { "aspect_ratio": "16:9", "resolution": "2K" }, + "target": { "target_type": "temporary" } + }' +``` + +- Set `aspect_ratio` to the slot's ratio, or the nearest supported one, and choose a `resolution` that meets the minimum source size. +- For text-heavy or vector needs, `mode: auto` picks a suitable model. Only pin a `model.id` if the user asks. +- If an existing image is close to what you need, adapt it in step 6 instead of generating from scratch. + +**Verify the preview** by viewing `data.assets[0].storage.secure_url`. Score it with the step 5 rubric. If it scores under 14, rewrite the prompt to fix what's wrong (name the specific problem, for example "the subject is centered, move it to the right third") and try again. Stop after 3 attempts per slot, keep the best result, and flag the slot in the report. + +**Save the approved image** by uploading the preview URL before it expires, so you keep exactly the image you checked: + +```bash +curl -s -X POST "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/image/upload" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -F "file=" \ + -F "public_id=/" \ + -F "tags=ai-generated,image-picker" \ + -F "context=alt=|prompt=" +``` + +### 8. Deliver with slot-sized transformations + +Build each delivery URL with cloudinary-transformations. The defaults for a slot are: + +- Crop to the slot: `c_fill,g_auto,h_,w_`, with `ar_` for fluid layouts +- Always optimize: `f_auto/q_auto` as the final components +- Responsive images: a `srcset` at 1x and 2x the display width, or `w_auto` where the site uses Client Hints +- Overlay text: if contrast is weak, darken behind the text with `e_brightness:-20` or a gradient overlay rather than choosing a busier image + +Example for a 1440x600 hero: `https://res.cloudinary.com//image/upload/c_fill,g_auto,h_600,w_1440/f_auto/q_auto/` + +Write meaningful `alt` text for every image, based on what the image actually shows and why it's on the page. Use an empty `alt=""` only for purely decorative images. + +When replacing an existing image, change only the image source, size, and `alt`. Keep the surrounding markup, classes, and loading behavior. + +### 9. Self-check the rendered page + +Before handing back, open the page and check it, using a browser tool if you have one, or by fetching and viewing each delivery URL if not: + +- [ ] Every delivery URL returns HTTP 200 and an image, not an error placeholder +- [ ] Each image shows what its slot needs, at the size it's displayed +- [ ] No key subject is cropped badly (cut-off heads, products cut in half) +- [ ] Overlay text is readable over the image +- [ ] The images look consistent together on the page +- [ ] No image appears blurry or pixelated at 2x + +Fix any failure by returning to step 5 for that slot (next candidate), step 6 (edit), or step 7 (new generation). Limit this to 2 fix rounds, then report what's left. + +### 10. Report to the user + +End with a short table, one row per slot: + +| Slot | Source | Asset | Score | Why | +|---|---|---|---|---| +| `home-hero` | Library | `samples/autumn-path` | 17/20 | Wide autumn path, clean sky for the headline | +| `menu-banner` | Adapted | `bakery-site/menu-banner` | 16/20 | Library photo was 4:3; extended to 21:9 with generative fill | +| `about-team` | Generated | `bakery-site/about-team` | 15/20 | No team photos in the library; generated a matching portrait | + +Also list any slots you flagged, any images you edited or generated and saved (with their public IDs and the original asset for edits), and anything the user should review, such as generated images of people. + +## Common Mistakes + +- Assuming Visual Search is available: test it, and fall back to another discovery method without fuss +- Running an auto-tagging or captioning pass on the user's assets without asking +- Generating from scratch when an edit to an existing image would fix the problem +- Overwriting the original asset with an edited version, or leaving a generative edit in a `srcset` URL so it runs again for every width +- Choosing from the public ID or tags without viewing the image +- Searching with the page's marketing copy instead of a visual description +- Choosing a small image and scaling it up: check `width` and `height` against the minimum source size +- Placing a portrait image in a wide banner and relying on `g_auto` to rescue it +- Using the same image twice on one page +- Generating before searching, or saving every generation attempt to the product environment +- Putting API credentials in client-side code From 4bf1a0126fa82d91a0dcdc6fcdab90cf7a96985d Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 12:49:12 +0000 Subject: [PATCH 2/6] Apply image picker fixes from first test run - Always ask for write permission before editing, generating, or saving - Treat empty Visual Search results as unavailable - Add a generation budget check using limits.addons_quota - Send accepted images with fixable flaws (logos, mismatched backgrounds) to step 6 - Guide resolution choice for wide slots - Self-check over local HTTP, not file://, at desktop and phone widths - Browse small scopes with contact sheets Co-Authored-By: Claude Opus 5.5 --- .../cloudinary-image-picker/SKILL.md | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md index 7988602..1b963cd 100644 --- a/skills/use-cases/cloudinary-image-picker/SKILL.md +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -4,7 +4,7 @@ description: "End-to-end recipe for choosing the right images for a website from license: MIT metadata: author: cloudinary - version: '0.1.0' + version: '0.2.0' internal: true --- @@ -41,7 +41,7 @@ Copy this checklist and track progress: ``` - [ ] 1. Inventory image slots -- [ ] 2. Confirm scope with the user (if needed) +- [ ] 2. Confirm scope and write permission with the user - [ ] 3. Write search queries per slot - [ ] 4. Search and collect candidates - [ ] 5. Score candidates and choose @@ -70,15 +70,15 @@ Before searching, build a slot list from the page code, the design, or your own Read the copy closely and connect the dots. A section titled "Fresh from our kitchen" above a bakery menu needs warm, close-up food photography, not a generic "food" image. A "Meet the team" grid needs consistent head-and-shoulders portraits, not mixed group shots. -### 2. Confirm scope with the user +### 2. Confirm scope and permissions with the user -Ask one short, batched question only when the answer changes the search. Skip it when the user already said, or when the request is clearly open. Useful questions: +Ask one short, batched question before you search. Skip a scope or style question when the user already answered it, but **always ask for write permission** unless the user already gave it: editing and generating create new assets in their product environment and use add-on quota, and without explicit permission your agent's safety checks may block the upload at the end of the run, after the quota is already spent. -- Limit the search to a folder, tag, or collection? (for example, only assets tagged `approved` or `CC0`) -- Any style preference: photography or illustration, people or no people, color mood? -- May you generate new images when nothing in the library fits, and save them to the product environment? +- **Scope**: limit the search to a folder, tag, or collection? (for example, only assets tagged `approved` or `CC0`) +- **Style**: photography or illustration, people or no people, color mood? +- **Write permission**: may you edit existing images or generate new ones when nothing in the library fits, and save the results to the product environment as new assets? Mention the quota cost (see [Check the generation budget](#check-the-generation-budget)). -If the user doesn't answer or says to go ahead, search all public images and generate where needed. +If the user says to go ahead without answering, search all public images, and edit or generate where needed. If they decline write permission, use library images only and flag any slots that don't reach the acceptance score. ### 3. Write search queries per slot @@ -108,7 +108,7 @@ Pick the first method that works for the product environment and the user's scop | C. Search API on tags and captions | The scope is larger, and assets have auto-tags or captions | Content keywords | | D. Search API on existing tags and names | None of the above | Whatever keywords the uploader added | -To test for Visual Search, run one visual search call. An error saying the feature isn't enabled means it's unavailable: move on without mentioning it again. To size the scope, run a Search API call with the scope expression and read `total_count`. +To test for Visual Search, run one visual search call with a broad query that should match something in any library, such as `outdoor` or `person`. Treat it as unavailable if the call returns an error saying the feature isn't enabled, or if it returns no results: the feature may be off, or the images may not be indexed yet. Move on without mentioning it again. To size the scope, run a Search API call with the scope expression and read `total_count`. #### A. Visual Search @@ -142,7 +142,8 @@ curl -s -X POST "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/resource ``` - Drop images that are too small for every slot (`width` and `height` below the smallest slot's display size) before viewing. -- View each remaining image once as a small thumbnail (`c_limit,w_300/f_jpg/q_auto`) and write a one-line description of it. Reuse these descriptions for every slot instead of viewing the images again. +- View the remaining images as **contact sheets**: download small thumbnails (`c_limit,w_300/f_jpg/q_auto`) and tile 12 to 20 of them into one grid image, each labeled with its public ID and pixel size (for example, with ImageMagick `montage` or Pillow). Viewing a few sheets is much faster than viewing each image on its own. +- Write a one-line description of each image from the sheets. Reuse these descriptions for every slot instead of viewing the images again. View a shortlisted image on its own, at a larger size, before you score it. - Match descriptions against each slot's needs to build its shortlist. #### C. Search API on tags and captions @@ -188,7 +189,9 @@ Maximum score: 20. Rules: - **Accept** the highest scorer if it reaches **14 or more**. - **Don't reuse** one asset in two slots on the same page, unless the design intends it. - **Check crop fit** by comparing aspect ratios: a 4:3 source in a 21:9 hero loses most of its height. `g_auto` helps, but can't add pixels that aren't there. +- **Third-party logos and brand names** on products (for example, a brand logo on sunglasses) score 0 on Clean for a store or brand site, because they misrepresent what's for sale. - If no candidate reaches 14, but one scores 10 or more and an edit could fix what it's missing, the slot goes to step 6. Otherwise, it goes to step 7. +- **An accepted image with a fixable flaw also goes to step 6**, when you have write permission. For example: a visible logo (remove it), or a product shot whose background doesn't match the other product cards (replace the background). Passing the acceptance score doesn't mean the image can't be improved. **Optional second opinion**: if the [Cloudinary AI Vision add-on](https://cloudinary.com/documentation/cloudinary_ai_vision_addon.md?install_source=skillspack&referrer=image-picker-skill) is available, use it to check slot-specific details on the top 2 or 3 candidates, for example, whether there's empty space for a headline. Ask yes-or-no questions with `ai_vision_general`: @@ -211,6 +214,7 @@ Record the score and a one-line reason for each choice. You need them for the re Editing an existing image is often better than generating a new one: it keeps a real photo, matches the rest of the library, and costs less. Consider it for: - A near-miss candidate from step 5 that has the right subject but one fixable problem +- An accepted candidate with a fixable flaw, such as a logo, or a background that doesn't match the images next to it - The slot's current image, when you're replacing or refreshing it. For example, a summer hero can become an autumn one by changing its background or season, while keeping the same people and layout. Match the problem to the fix: @@ -250,6 +254,14 @@ Then: Use the [Image Generation API](https://cloudinary.com/documentation/image_generation_addon.md?install_source=skillspack&referrer=image-picker-skill) when no existing asset fits. If the user said not to generate, leave the best candidate in place and flag the slot in the report. +#### Check the generation budget + +Every `text_to_image` and `image_to_image` call uses Image Generation quota, and a free plan's allotment runs out after a handful of images. Every response reports the quota in `limits.addons_quota` (`used_by_request`, `remaining`, `limit`). + +- After the first call, work out how many more images the remaining quota allows, and plan around it: generate the slots that matter most first (hero, then products, then decorative backgrounds). +- Count retries against the budget. If the budget can't cover every slot plus a retry each, tell the user which slots you'll leave as library near-misses, before you spend it. +- Report the quota used and remaining at the end. + **Write the prompt** from the slot inventory, not from the search query. A good prompt states: 1. Subject and action: "a barista pouring latte art into a ceramic cup" @@ -275,7 +287,8 @@ curl -s -X POST "https://api.cloudinary.com/v2/generate/$CLOUDINARY_CLOUD_NAME/t }' ``` -- Set `aspect_ratio` to the slot's ratio, or the nearest supported one, and choose a `resolution` that meets the minimum source size. +- Set `aspect_ratio` to the slot's ratio, or the nearest supported one, and choose a `resolution` that meets the minimum source size. `2K` is about 2048 pixels on the long side, which is enough for slots up to about 1000 CSS pixels wide at 2x. +- For wider slots, such as a full-width hero, request the highest resolution the API supports. If the result is still under the minimum source size, upscale the approved image with `e_upscale` before saving it, or save it as is and flag the slot in the report. - For text-heavy or vector needs, `mode: auto` picks a suitable model. Only pin a `model.id` if the user asks. - If an existing image is close to what you need, adapt it in step 6 instead of generating from scratch. @@ -309,7 +322,9 @@ When replacing an existing image, change only the image source, size, and `alt`. ### 9. Self-check the rendered page -Before handing back, open the page and check it, using a browser tool if you have one, or by fetching and viewing each delivery URL if not: +Before handing back, open the page and check it, using a browser tool if you have one, or by fetching and viewing each delivery URL if not. + +Check the page as a visitor sees it, with all its styles, scripts, and fonts loaded. Use the project's dev server if it has one. For a static site, serve the folder over local HTTP (for example, `python3 -m http.server`) rather than opening the file directly: some browser tools load a `file://` page without its stylesheet, which hides crop and overlay problems. If the page renders unstyled, fix that before checking anything else. Take a screenshot at desktop width and one at phone width. - [ ] Every delivery URL returns HTTP 200 and an image, not an error placeholder - [ ] Each image shows what its slot needs, at the size it's displayed @@ -330,12 +345,15 @@ End with a short table, one row per slot: | `menu-banner` | Adapted | `bakery-site/menu-banner` | 16/20 | Library photo was 4:3; extended to 21:9 with generative fill | | `about-team` | Generated | `bakery-site/about-team` | 15/20 | No team photos in the library; generated a matching portrait | -Also list any slots you flagged, any images you edited or generated and saved (with their public IDs and the original asset for edits), and anything the user should review, such as generated images of people. +Also list the discovery method you used, any slots you flagged, any images you edited or generated and saved (with their public IDs and the original asset for edits), the Image Generation quota used and remaining, and anything the user should review, such as generated images of people presented as real staff or customers. ## Common Mistakes - Assuming Visual Search is available: test it, and fall back to another discovery method without fuss +- Starting to generate without asking for write permission, then being blocked from saving after the quota is spent - Running an auto-tagging or captioning pass on the user's assets without asking +- Accepting a product shot with a third-party logo, or a background that clashes with the cards next to it, instead of fixing it in step 6 +- Checking the page from a `file://` URL that loads without its stylesheet - Generating from scratch when an edit to an existing image would fix the problem - Overwriting the original asset with an edited version, or leaving a generative edit in a `srcset` URL so it runs again for every width - Choosing from the public ID or tags without viewing the image From adbac2138c44907cb3da4da674bac313be3ff9bf Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 13:05:46 +0000 Subject: [PATCH 3/6] Add per-breakpoint crops to image picker delivery Record each aspect ratio a slot uses across breakpoints, and deliver a separate g_auto crop per ratio with picture/source instead of relying on CSS object-fit center cropping, which cut the subject out of a phone hero in testing. Check crops at desktop and phone width. Co-Authored-By: Claude Opus 5.5 --- .../cloudinary-image-picker/SKILL.md | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md index 1b963cd..fbb8d37 100644 --- a/skills/use-cases/cloudinary-image-picker/SKILL.md +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -4,7 +4,7 @@ description: "End-to-end recipe for choosing the right images for a website from license: MIT metadata: author: cloudinary - version: '0.2.0' + version: '0.3.0' internal: true --- @@ -63,7 +63,7 @@ Before searching, build a slot list from the page code, the design, or your own | Context | The heading, body text, and calls to action closest to the slot. This is the main signal for what the image should show. | | Site context | Brand, audience, tone, color palette, season or campaign | | Display size | Rendered width and height in CSS pixels at the largest breakpoint, from the CSS, the component props, or the layout | -| Aspect ratio | From the display size, or from `aspect-ratio`, `object-fit`, or fixed width and height | +| Aspect ratio | From the display size, or from `aspect-ratio`, `object-fit`, or fixed width and height. Check the media queries too: if the ratio changes at a breakpoint (for example, a 12:5 hero that becomes 4:5 on phones), record each ratio and its breakpoint. | | Minimum source size | Display size multiplied by 2 for high-density screens. For example, a 1440x600 hero needs a source of at least 2880x1200, or at least 1920 wide as a floor. | | Overlay | Whether text or buttons sit on top of the image, and where. The image needs a calm, low-detail area there. | | Current image | The existing URL, if any, and why it's being replaced | @@ -316,6 +316,23 @@ Build each delivery URL with cloudinary-transformations. The defaults for a slot Example for a 1440x600 hero: `https://res.cloudinary.com//image/upload/c_fill,g_auto,h_600,w_1440/f_auto/q_auto/` +**When a slot's aspect ratio changes at a breakpoint**, deliver a separate crop for each ratio. Don't rely on one wide image plus CSS `object-fit: cover`: the browser crops from the center and can cut the subject out entirely. Use `` with a `` per breakpoint, each with its own `c_fill,g_auto` crop, so Cloudinary keeps the subject in frame at every ratio: + +```html + + + <ALT_TEXT> + +``` + +- Keep the existing `` class and attributes on the `` inside ``, so the site's CSS still applies. +- Score the image for every ratio, not only the widest one. A subject on the right third of a wide hero may be the only thing a phone crop needs to keep, and `g_auto` handles that. If the subject still gets cut off, or the overlay text has nowhere calm to sit at a ratio, look for a better candidate, or extend the image with generative fill in step 6. +- If the overlay text moves at a breakpoint (for example, from the left side to the top), check that the crop for that breakpoint has a calm area where the text now sits. + Write meaningful `alt` text for every image, based on what the image actually shows and why it's on the page. Use an empty `alt=""` only for purely decorative images. When replacing an existing image, change only the image source, size, and `alt`. Keep the surrounding markup, classes, and loading behavior. @@ -328,7 +345,7 @@ Check the page as a visitor sees it, with all its styles, scripts, and fonts loa - [ ] Every delivery URL returns HTTP 200 and an image, not an error placeholder - [ ] Each image shows what its slot needs, at the size it's displayed -- [ ] No key subject is cropped badly (cut-off heads, products cut in half) +- [ ] No key subject is cropped badly (cut-off heads, products cut in half), at desktop or phone width - [ ] Overlay text is readable over the image - [ ] The images look consistent together on the page - [ ] No image appears blurry or pixelated at 2x @@ -360,6 +377,7 @@ Also list the discovery method you used, any slots you flagged, any images you e - Searching with the page's marketing copy instead of a visual description - Choosing a small image and scaling it up: check `width` and `height` against the minimum source size - Placing a portrait image in a wide banner and relying on `g_auto` to rescue it +- Delivering one wide crop to a slot whose aspect ratio changes on phones, so CSS center-cropping cuts out the subject - Using the same image twice on one page - Generating before searching, or saving every generation attempt to the product environment - Putting API credentials in client-side code From 84486b2570bc6a8727f9bfea59620ab3c7a44427 Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 13:44:53 +0000 Subject: [PATCH 4/6] Add matching-set generation to image picker Generate one reference image for a set of similar slots, then make the rest with image_to_image using it as the reference. In testing this kept product cards consistent and cost far less per image than text_to_image. Also tell agents to read used_by_request rather than assume a fixed cost. Co-Authored-By: Claude Opus 5.5 --- skills/use-cases/cloudinary-image-picker/SKILL.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md index fbb8d37..7b3ad72 100644 --- a/skills/use-cases/cloudinary-image-picker/SKILL.md +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -4,7 +4,7 @@ description: "End-to-end recipe for choosing the right images for a website from license: MIT metadata: author: cloudinary - version: '0.3.0' + version: '0.4.0' internal: true --- @@ -260,8 +260,18 @@ Every `text_to_image` and `image_to_image` call uses Image Generation quota, and - After the first call, work out how many more images the remaining quota allows, and plan around it: generate the slots that matter most first (hero, then products, then decorative backgrounds). - Count retries against the budget. If the budget can't cover every slot plus a retry each, tell the user which slots you'll leave as library near-misses, before you spend it. +- The cost per image varies with the model, the resolution, and the endpoint, so read `used_by_request` after each call instead of assuming a fixed price. Request only the resolution the slot needs: a 4K image can cost several times as much as a 1K one. - Report the quota used and remaining at the end. +#### Generate matching sets from one reference + +When several slots need images that look alike, such as product cards, a gallery, or a set of article headers: + +1. Generate or choose **one** image that sets the look: the setting, props, light, and palette. Often this is the hero, or the first card. +2. Make the rest with the `image_to_image` endpoint, passing that image as the reference, and describe only what changes for each slot: "Same kraft bag, table, and light as [1], with dark espresso beans and a small espresso cup beside it". + +This keeps the set consistent, which separate `text_to_image` prompts rarely do, and it's often much cheaper per image. Check `used_by_request` on the first one to confirm the saving before you make the rest. + **Write the prompt** from the slot inventory, not from the search query. A good prompt states: 1. Subject and action: "a barista pouring latte art into a ceramic cup" @@ -380,4 +390,5 @@ Also list the discovery method you used, any slots you flagged, any images you e - Delivering one wide crop to a slot whose aspect ratio changes on phones, so CSS center-cropping cuts out the subject - Using the same image twice on one page - Generating before searching, or saving every generation attempt to the product environment +- Generating a matching set (product cards, gallery) with separate text prompts, so the images don't match and cost more, instead of using one image as the `image_to_image` reference - Putting API credentials in client-side code From e368533383ace58c7bf9422443bb6a2f5ff7ee38 Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 13:55:56 +0000 Subject: [PATCH 5/6] Add optional visible AI disclosure to image picker Ask whether to label AI-generated and AI-edited images. If yes, upload the four AI label variants when missing, pick one per crop from the brightness and busyness of its bottom-right corner, and apply it as a conditional overlay on cld_ai_generated after the crop. Always save AI images with ai_generated=true so the flag is set, and mention the disclosure in alt text. Co-Authored-By: Claude Opus 5.5 --- .../cloudinary-image-picker/SKILL.md | 60 +++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md index 7b3ad72..45ae2d9 100644 --- a/skills/use-cases/cloudinary-image-picker/SKILL.md +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -4,7 +4,7 @@ description: "End-to-end recipe for choosing the right images for a website from license: MIT metadata: author: cloudinary - version: '0.4.0' + version: '0.5.0' internal: true --- @@ -77,8 +77,9 @@ Ask one short, batched question before you search. Skip a scope or style questio - **Scope**: limit the search to a folder, tag, or collection? (for example, only assets tagged `approved` or `CC0`) - **Style**: photography or illustration, people or no people, color mood? - **Write permission**: may you edit existing images or generate new ones when nothing in the library fits, and save the results to the product environment as new assets? Mention the quota cost (see [Check the generation budget](#check-the-generation-budget)). +- **AI disclosure**: when you have write permission, ask whether the site should show a visible "AI" label on AI-generated and AI-edited images. Some regulations, such as Article 50 of the EU AI Act, require AI-generated media to be disclosed to the people viewing it. Don't give legal advice: if the user isn't sure, suggest they check with their legal or compliance team. See [Add a visible AI label](#add-a-visible-ai-label). -If the user says to go ahead without answering, search all public images, and edit or generate where needed. If they decline write permission, use library images only and flag any slots that don't reach the acceptance score. +If the user says to go ahead without answering, search all public images, and edit or generate where needed, without an AI label. If they decline write permission, use library images only and flag any slots that don't reach the acceptance score. ### 3. Write search queries per slot @@ -248,7 +249,7 @@ curl -s -X POST "https://api.cloudinary.com/v2/generate/$CLOUDINARY_CLOUD_NAME/i Then: 1. **Check the result**: open the transformation URL (the first request can take a while, since the edit runs then) or the `image_to_image` preview URL, and view it. Score it with the step 5 rubric. If it scores under 14, try a different fix or a clearer prompt, up to 2 attempts, then go to step 7. -2. **Save the approved result as a new asset**, using the same upload call as in step 7, with `tags=ai-edited,image-picker`. Don't overwrite the original. Saving also means the responsive sizes in step 8 resize one fixed image, instead of running the generative edit again for every width. +2. **Save the approved result as a new asset**, using the same upload call as in step 7, with `tags=ai-edited,image-picker` and `ai_generated=true`. Don't overwrite the original. Saving also means the responsive sizes in step 8 resize one fixed image, instead of running the generative edit again for every width. ### 7. Generate images for unfilled slots @@ -312,9 +313,12 @@ curl -s -X POST "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/image/up -F "file=" \ -F "public_id=/" \ -F "tags=ai-generated,image-picker" \ - -F "context=alt=|prompt=" + -F "context=alt=|prompt=" \ + -F "ai_generated=true" ``` +Always pass `ai_generated=true` when you save a generated or AI-edited image, whether or not the user wants a visible label. It sets the asset's [AI-generated field](https://cloudinary.com/documentation/content_provenance_and_authenticity.md?install_source=skillspack&referrer=image-picker-skill#provenance_and_ai_fields), which search and the conditional AI label in step 8 rely on. Re-uploading a preview URL doesn't set it automatically, and the field can't be added to an asset after upload. + ### 8. Deliver with slot-sized transformations Build each delivery URL with cloudinary-transformations. The defaults for a slot are: @@ -347,6 +351,49 @@ Write meaningful `alt` text for every image, based on what the image actually sh When replacing an existing image, change only the image source, size, and `alt`. Keep the surrounding markup, classes, and loading behavior. +#### Add a visible AI label + +If the user wants AI disclosure (step 2), add an "AI" label in the bottom-right corner of every generated or AI-edited image, as a [conditional overlay](https://cloudinary.com/documentation/content_provenance_and_authenticity.md?install_source=skillspack&referrer=image-picker-skill#adding_a_visible_ai_disclosure) applied at delivery. The original asset is never changed. + +**1. Make sure the labels are in the product environment.** There are four versions of the label, all round "AI" badges on a transparent canvas: + +| Public ID | Look | Use on | +|---|---|---| +| `ai-labels/LABEL_AI_white_transparent` | Translucent white circle, black "AI" | A calm, dark corner | +| `ai-labels/LABEL_AI_black_transparent` | Translucent black circle, white "AI" | A calm, light corner | +| `ai-labels/LABEL_AI_white` | Solid white circle, black "AI" | A busy or mid-tone corner that's darker overall | +| `ai-labels/LABEL_AI_black` | Solid black circle, white "AI" | A busy or mid-tone corner that's lighter overall | + +Check for each label with the Admin API (`GET /resources/image/upload/ai-labels/`). Upload any that are missing, from Cloudinary's copies, keeping the same names: + +```bash +for n in white_transparent black_transparent white black; do + curl -s -X POST "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/image/upload" \ + -u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \ + -F "file=https://res.cloudinary.com/demo/image/upload/v1792417795/docs/icons/LABEL_AI_$n.png" \ + -F "public_id=ai-labels/LABEL_AI_$n" \ + -F "overwrite=false" \ + -F "tags=image-picker" +done +``` + +Don't set `ai_generated` on the labels themselves. + +**2. Choose a label for each crop.** View the bottom-right corner of each delivered crop: the label sits on the crop, not the original, and each breakpoint crop has a different corner. Judge the corner's brightness and how busy it is, and pick from the table. When in doubt, choose a solid label: readability matters more than subtlety. The labels don't need to match each other across a page. + +**3. Size the label.** Aim for a label about 48 to 64 CSS pixels across on screen. Scale it in pixels relative to the crop's delivered width: for example, `w_64` on a crop delivered at 1x, and `w_128` on the 2x crop of the same slot. The badge has transparent padding built in, so it doesn't need an extra offset from the corner. + +**4. Add the overlay after the crop and before `f_auto/q_auto`**, so it lands in the corner of the crop the visitor sees: + +``` +c_fill,g_auto,h_600,w_1440/if_ctx:!cld_ai_generated!_eq_!true!/l_ai-labels:LABEL_AI_black_transparent/c_scale,w_64/fl_layer_apply,g_south_east/if_end/f_auto/q_auto/ +``` + +- The condition shows the label only when the asset's AI-generated field is `true`, so the same URL pattern is safe to use on library images too. It depends on the asset having been saved with `ai_generated=true` (step 7). +- For an AI-generated asset saved without `ai_generated=true`, drop the `if_ctx` and `if_end` components and add the overlay unconditionally. +- Add the overlay to every URL for the slot: each `srcset` width, each `` crop, and CSS `background-image` URLs. +- Add the disclosure to the alt text too, so screen reader users get it: for example, "AI-generated image: two hikers on an autumn trail". + ### 9. Self-check the rendered page Before handing back, open the page and check it, using a browser tool if you have one, or by fetching and viewing each delivery URL if not. @@ -357,6 +404,7 @@ Check the page as a visitor sees it, with all its styles, scripts, and fonts loa - [ ] Each image shows what its slot needs, at the size it's displayed - [ ] No key subject is cropped badly (cut-off heads, products cut in half), at desktop or phone width - [ ] Overlay text is readable over the image +- [ ] If AI labels are on: every generated or AI-edited image shows its label, clearly readable, not hidden under text or buttons, and not clipped by CSS cropping, at desktop and phone width - [ ] The images look consistent together on the page - [ ] No image appears blurry or pixelated at 2x @@ -372,7 +420,7 @@ End with a short table, one row per slot: | `menu-banner` | Adapted | `bakery-site/menu-banner` | 16/20 | Library photo was 4:3; extended to 21:9 with generative fill | | `about-team` | Generated | `bakery-site/about-team` | 15/20 | No team photos in the library; generated a matching portrait | -Also list the discovery method you used, any slots you flagged, any images you edited or generated and saved (with their public IDs and the original asset for edits), the Image Generation quota used and remaining, and anything the user should review, such as generated images of people presented as real staff or customers. +Also list the discovery method you used, any slots you flagged, any images you edited or generated and saved (with their public IDs and the original asset for edits), the Image Generation quota used and remaining, which images carry an AI label (and which label version), and anything the user should review, such as generated images of people presented as real staff or customers. ## Common Mistakes @@ -392,3 +440,5 @@ Also list the discovery method you used, any slots you flagged, any images you e - Generating before searching, or saving every generation attempt to the product environment - Generating a matching set (product cards, gallery) with separate text prompts, so the images don't match and cost more, instead of using one image as the `image_to_image` reference - Putting API credentials in client-side code +- Saving a generated image without `ai_generated=true`, so the conditional AI label never shows and the flag can't be added later +- Placing the AI label before the crop, so it's cropped out, or choosing its version from the full image instead of the corner of each crop From 023e6cd5f0eec2b559e32670d166b226bebf988f Mon Sep 17 00:00:00 2001 From: carlevison Date: Wed, 28 Oct 2026 15:08:30 +0000 Subject: [PATCH 6/6] Cap generation at 2K and limit upscaling in image picker A 4K hero cost 19 Image Generation units in testing. Generate wide images at 2K instead, and when upscaling with e_upscale (always 4x), follow it with c_limit at the slot's minimum source size before saving. Co-Authored-By: Claude Opus 5.5 --- skills/use-cases/cloudinary-image-picker/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/use-cases/cloudinary-image-picker/SKILL.md b/skills/use-cases/cloudinary-image-picker/SKILL.md index 45ae2d9..0abc6a7 100644 --- a/skills/use-cases/cloudinary-image-picker/SKILL.md +++ b/skills/use-cases/cloudinary-image-picker/SKILL.md @@ -4,7 +4,7 @@ description: "End-to-end recipe for choosing the right images for a website from license: MIT metadata: author: cloudinary - version: '0.5.0' + version: '0.5.1' internal: true --- @@ -261,7 +261,7 @@ Every `text_to_image` and `image_to_image` call uses Image Generation quota, and - After the first call, work out how many more images the remaining quota allows, and plan around it: generate the slots that matter most first (hero, then products, then decorative backgrounds). - Count retries against the budget. If the budget can't cover every slot plus a retry each, tell the user which slots you'll leave as library near-misses, before you spend it. -- The cost per image varies with the model, the resolution, and the endpoint, so read `used_by_request` after each call instead of assuming a fixed price. Request only the resolution the slot needs: a 4K image can cost several times as much as a 1K one. +- The cost per image varies with the model, the resolution, and the endpoint, so read `used_by_request` after each call instead of assuming a fixed price. Request only the resolution the slot needs, and never more than `2K`: in testing, one 4K hero cost 19 units, about as much as 7 smaller images together. For wider slots, generate at `2K` and upscale (see below). - Report the quota used and remaining at the end. #### Generate matching sets from one reference @@ -299,7 +299,7 @@ curl -s -X POST "https://api.cloudinary.com/v2/generate/$CLOUDINARY_CLOUD_NAME/t ``` - Set `aspect_ratio` to the slot's ratio, or the nearest supported one, and choose a `resolution` that meets the minimum source size. `2K` is about 2048 pixels on the long side, which is enough for slots up to about 1000 CSS pixels wide at 2x. -- For wider slots, such as a full-width hero, request the highest resolution the API supports. If the result is still under the minimum source size, upscale the approved image with `e_upscale` before saving it, or save it as is and flag the slot in the report. +- For wider slots, such as a full-width hero, still generate at `2K`, which costs far less than `4K`. If the approved image is under the slot's minimum source size, upscale it when you save it: `e_upscale` always multiplies each dimension by 4, so follow it with `c_limit` to stop at the minimum source size, and save that derived image. For example, for a 1440x600 hero, save `e_upscale/c_limit,w_2880/` rather than the full 8192-pixel result. Upscaling doesn't use Image Generation quota. - For text-heavy or vector needs, `mode: auto` picks a suitable model. Only pin a `model.id` if the user asks. - If an existing image is close to what you need, adapt it in step 6 instead of generating from scratch.