{
  "name": "Cloudinary — Responsive srcset Builder (one image → paste-in <picture> HTML)",
  "nodes": [
    {
      "parameters": {},
      "id": "33330000-0000-4a01-9001-000000000001",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        320
      ]
    },
    {
      "parameters": {
        "resource": "upload",
        "operation": "uploadUrl",
        "url": "https://res.cloudinary.com/demo/image/upload/samples/landscapes/nature-mountains.jpg",
        "resource_type": "image",
        "additionalFields": {
          "public_id": "n8n_blog/srcset_demo",
          "tags": "n8n-blog,srcset-demo"
        }
      },
      "id": "33330000-0000-4a01-9001-000000000007",
      "name": "Upload Sample Image",
      "type": "n8n-nodes-cloudinary.cloudinary",
      "typeVersion": 1,
      "position": [
        520,
        320
      ]
    },
    {
      "parameters": {
        "jsCode": "// Fan the uploaded image out into one item per srcset width.\nconst publicId = $json.public_id;\nconst widths = [320, 640, 960, 1280, 1920];\nreturn widths.map(w => ({ json: { public_id: publicId, width: w } }));"
      },
      "id": "33330000-0000-4a01-9001-000000000002",
      "name": "Breakpoints",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        820,
        320
      ]
    },
    {
      "parameters": {
        "resource": "transform",
        "operation": "resizeImage",
        "transformPublicId": "={{ $json.public_id }}",
        "type": "upload",
        "resizeWidth": "={{ $json.width }}",
        "resizeHeight": 0,
        "resizeFit": "limit"
      },
      "id": "33330000-0000-4a01-9001-000000000003",
      "name": "Resize to Width",
      "type": "n8n-nodes-cloudinary.cloudinary",
      "typeVersion": 1,
      "position": [
        1120,
        320
      ]
    },
    {
      "parameters": {
        "resource": "transform",
        "operation": "optimizeImage",
        "transformPublicId": "={{ $('Breakpoints').item.json.public_id }}",
        "type": "upload",
        "continueFromTransformation": "={{ $json.transformation }}",
        "imageQuality": "auto"
      },
      "id": "33330000-0000-4a01-9001-000000000004",
      "name": "Optimize (f_auto/q_auto)",
      "type": "n8n-nodes-cloudinary.cloudinary",
      "typeVersion": 1,
      "position": [
        1420,
        320
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "// Assemble every width into a single <img srcset> snippet you can paste into any page.\nconst rows = $input.all().map((item, i) => ({\n  width: $('Breakpoints').all()[i].json.width,\n  url: item.json.secure_url,\n}));\nrows.sort((a, b) => a.width - b.width);\nconst srcset = rows.map(r => `${r.url} ${r.width}w`).join(', ');\nconst smallest = rows[0].url;\nconst html = `<img src=\"${smallest}\" srcset=\"${srcset}\" sizes=\"(max-width: 768px) 100vw, 50vw\" alt=\"Describe the image here\" loading=\"lazy\" />`;\nreturn [{ json: { srcset_html: html, sources: rows } }];"
      },
      "id": "33330000-0000-4a01-9001-000000000005",
      "name": "Build srcset HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1720,
        320
      ]
    },
    {
      "parameters": {
        "content": "## 🖼️ Responsive srcset Builder\n\n**One source image → a full responsive `srcset`**, every variant auto-optimized for the requesting browser. Stop hand-exporting `@1x/@2x` and shipping oversized images to phones.\n\n### What it does\n1. **Upload Sample Image** pulls a public demo image into *your* Cloudinary account (so the transforms resolve on your cloud).\n2. **Breakpoints** fans it out into one item per width you want (`320…1920`).\n3. **Resize to Width** builds a delivery URL per width using **Image: Resize** with *Limit* fit (never upscales).\n4. **Optimize** chains onto each (via **Continue From Transformation**) to add `f_auto/q_auto` — Cloudinary then serves AVIF/WebP/JPEG per browser, at the right quality.\n5. **Build srcset HTML** assembles one ready-to-paste `<img srcset=…>` block.\n\n### The payoff\nA single source asset powers crisp Retina displays *and* lightweight mobile loads — and the markup is generated for you. Add or remove a breakpoint by editing one array.\n\n### Make it yours\n- **Your image:** point *Upload Sample Image* at your own URL (or swap in a search/upload of real assets).\n- **Your breakpoints:** edit the `widths` array in *Breakpoints*.\n- **Use it:** copy `srcset_html` from *Build srcset HTML* into your template, or push it to your CMS via HTTP Request. Remember to set a real `alt`.\n\n### Setup\n👉 Add your **Cloudinary API** credential to the two Cloudinary nodes (Cloud name + API Key + Secret from the [Console](https://console.cloudinary.com/settings/api-keys)). Not included in this template.\n\n💾 **Then press `Cmd/Ctrl+S` to save before running.** That one save persists the credential to *every* Cloudinary node at once, so a full **Execute Workflow** run finds credentials everywhere. Skip the save and the run can fail node-after-node with *\"Node does not have any credentials set\"* — even though the credential looks selected. (If **Execute step** works but **Execute Workflow** doesn't, you forgot the save.)",
        "height": 1060,
        "width": 600
      },
      "id": "33330000-0000-4a01-9001-000000000006",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        200,
        560
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Upload Sample Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Sample Image": {
      "main": [
        [
          {
            "node": "Breakpoints",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Breakpoints": {
      "main": [
        [
          {
            "node": "Resize to Width",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resize to Width": {
      "main": [
        [
          {
            "node": "Optimize (f_auto/q_auto)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Optimize (f_auto/q_auto)": {
      "main": [
        [
          {
            "node": "Build srcset HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {}
}
