{
  "name": "tpl-scout",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -16,
        -160
      ],
      "id": "91c5706f-4f41-4cf9-8a6a-e2f898ee4793",
      "name": "When clicking \u2018Execute workflow\u2019"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -16,
        32
      ],
      "id": "049ea3e7-987c-4a3d-a4ed-b830b861fd88",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        432,
        -48
      ],
      "id": "9712668a-fb97-4fe4-b71d-965ccdf99d58",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "url": "={{ $json.link }}",
        "options": {}
      },
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1.2,
      "position": [
        656,
        -48
      ],
      "id": "71e42da3-8526-4664-ba36-f188d14fde89",
      "name": "RSS Read"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "0ff119b6-bdd7-476c-a960-44a1fe416a87",
              "name": "source",
              "value": "={{ $('Loop Over Items').item.json.source }}",
              "type": "string"
            },
            {
              "id": "bcf4522d-e462-41ef-9b65-eea474a55fab",
              "name": "title",
              "value": "={{ $json.title }}",
              "type": "string"
            },
            {
              "id": "8423669a-6d15-4420-a26a-fd44ecd2e310",
              "name": "link",
              "value": "={{ $json.link }}",
              "type": "string"
            },
            {
              "id": "9be6f9b4-c4ea-4504-9b35-d70a35df3b00",
              "name": "content",
              "value": "={{ $json.content.trim().slice(0, 350) }}",
              "type": "string"
            },
            {
              "id": "e381a2c2-6446-4f38-b525-44ab5c1c6482",
              "name": "isoDate",
              "value": "={{ $json.isoDate.split(\"T\")[0] }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        944,
        -48
      ],
      "id": "488b2162-ca21-4883-9bbc-3af63db41613",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "WigBivLV8CAGPxOg",
          "mode": "list",
          "cachedResultName": "tpl-sout-rss-links",
          "cachedResultUrl": "/projects/uabU37OVTmcWS1JM/datatables/WigBivLV8CAGPxOg"
        },
        "filters": {
          "conditions": [
            {
              "keyName": "status",
              "keyValue": "active"
            }
          ]
        },
        "returnAll": true
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        208,
        -48
      ],
      "id": "6e7b2ab4-654b-4914-8e13-b4af8ee29a6d",
      "name": "rss links"
    },
    {
      "parameters": {
        "jsCode": "const today = new Date().toISOString().split('T')[0];\nreturn $input.all().filter(flux => flux.json.isoDate === today);"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1232,
        32
      ],
      "id": "e28458be-ff41-4de1-a1ab-98f7d6e432f6",
      "name": "filter",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "jsCode": "return $input.all().filter(flux => Object.keys(flux.json).length > 0);"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        656,
        -336
      ],
      "id": "b728f39d-5293-4887-9390-0066260f2909",
      "name": "not empty"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Tu analyses une veille quotidienne de flux RSS pour Tol Product Lab, studio \nd'ing\u00e9nierie produit sp\u00e9cialis\u00e9 en automatisation (n8n), d\u00e9veloppement web, \ndesign UX/UI SaaS, et fonctionnalit\u00e9s IA pour produits.\n\nVoici les entr\u00e9es du jour :\n{{ $input.all().map(item => item.json) }}\n\nPour chaque entr\u00e9e pertinente (ignore les entr\u00e9es hors sujet ou trop mineures \npour justifier un traitement), produis :\n\n1. Un r\u00e9sum\u00e9 factuel en fran\u00e7ais, 2-3 phrases maximum, sans reformulation \n   promotionnelle ni jugement de valeur.\n2. Le domaine dominant, une seule valeur parmi : automatisation, ia-generative, \n   dev-web, ux-design, geo-seo.\n3. 1 \u00e0 3 id\u00e9es d'angle d'article, chacune avec :\n   - un titre de travail (pas d\u00e9finitif, juste une direction)\n   - une justification courte : pourquoi ce sujet a une chance r\u00e9elle d'int\u00e9resser \n     un lecteur francophone (PME, fondateur SaaS, indie hacker) et pas juste \n     \"c'est une actu tech\"\n   - le type d'article sugg\u00e9r\u00e9 parmi : opinion, tutoriel, etude-de-cas, build\n   Si l'entr\u00e9e ne justifie aucun angle exploitable, laisse ce champ vide plut\u00f4t \n   que de forcer une id\u00e9e artificielle.\n\nIgnore toute entr\u00e9e qui ne concerne pas directement l'automatisation, l'IA \nappliqu\u00e9e aux produits, le d\u00e9veloppement web, le design UX/UI ou le SEO/GEO.\n\nR\u00e9ponds uniquement en JSON valide, structure suivante, sans texte avant ni \napr\u00e8s :\n\n[\n  {\n    \"source\": \"string\",\n    \"titre_original\": \"string\",\n    \"lien\": \"string\",\n    \"resume\": \"string\",\n    \"domaine\": \"automatisation | ia-generative | dev-web | ux-design | geo-seo\",\n    \"angles\": [\n      {\n        \"titre_travail\": \"string\",\n        \"justification\": \"string\",\n        \"type_suggere\": \"opinion | tutoriel | etude-de-cas | build\"\n      }\n    ]\n  }\n]",
        "messages": {
          "messageValues": []
        },
        "batching": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.9,
      "position": [
        880,
        -448
      ],
      "id": "7f9ebece-3d01-4d30-ab2b-6025a18f915f",
      "name": "Basic LLM Chain",
      "retryOnFail": true,
      "maxTries": 5,
      "waitBetweenTries": 1500,
      "executeOnce": true
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1.1,
      "position": [
        960,
        -224
      ],
      "id": "e8971644-96d7-4140-8d02-cfc23490901d",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "24fc6cc5-576a-41ec-be53-6ebba99ab447",
              "leftValue": "={{ $json.text }}",
              "rightValue": "[]",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1232,
        -336
      ],
      "id": "15539d21-1a48-475c-92eb-fba5781c8589",
      "name": "sucedeed ?"
    },
    {
      "parameters": {
        "jsCode": "const response = JSON.parse($input.item.json.text);\n\nreturn response.map(item => ({...item}));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1456,
        -336
      ],
      "id": "1ab489e3-8ad4-4d7c-8923-d7bdee51ed3c",
      "name": "parser"
    },
    {
      "parameters": {
        "sendTo": "eyitolasagbohan@gmail.com",
        "subject": "={{ $json.object }}",
        "message": "={{ $json.emailHtml }}",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        2128,
        -144
      ],
      "id": "a154837e-41d3-4a40-a3ed-797eff5d6ba3",
      "name": "Send a message",
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0",
          "mode": "list",
          "cachedResultName": "rssIdeas",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "tpl-scout",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit#gid=0"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        1680,
        -432
      ],
      "id": "49bed0e0-22de-4b3d-b10f-a2d83b8a253e",
      "name": "existing rss",
      "executeOnce": true,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0",
          "mode": "list",
          "cachedResultName": "rssIdeas",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "tpl-scout",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "source": "={{ $json.source }}",
            "titre_original": "={{ $json.titre_original }}",
            "lien": "={{ $json.lien }}",
            "resume": "={{ $json.resume }}",
            "domaine": "={{ $json.domaine }}",
            "angles": "={{ $json.angles }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "source",
              "displayName": "source",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "titre_original",
              "displayName": "titre_original",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "lien",
              "displayName": "lien",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "resume",
              "displayName": "resume",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "domaine",
              "displayName": "domaine",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "angles",
              "displayName": "angles",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2128,
        -336
      ],
      "id": "5d69e64d-7535-461b-b82b-e6e1c22e7e37",
      "name": "news rss",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "5aeef6f2-4371-477f-ad61-432ba231fbaa",
              "leftValue": "={{ Object.keys($json).length }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1904,
        -336
      ],
      "id": "384459ef-f386-41b0-8512-20af44a3e2f0",
      "name": "new rss ?"
    },
    {
      "parameters": {
        "jsCode": "const today = new Date().toISOString().split(\"T\")[0];\nconst rssByDomain = Object.groupBy($input.all(), (item) => item.json.domaine);\nconst domaines = Object.keys(rssByDomain);\n\nfunction blocMessageSetter(rssList) {\n  const message = rssList.map(item => (\n    `<h3><a href=\"${item.lien}\">${item.titre_original}</a></h3>\n  <p>${item.resume}</p>\n  <p><em>Source : ${item.source}</em></p>\n  <ul>\n    ${item.angles.map(angle => (`<li><strong>${angle.titre_travail}</strong> \u2014 ${angle.type_suggere}<br>\n        <span style=\"color:#666;\">${angle.justification}</span></li>`))}\n  </ul>\n  <hr><br>`\n  ));\n  return message;\n}\n\nlet emailHtml = \"\";\nfor (const domaine of domaines){\n  const rssList = rssByDomain[domaine].map(item => ({...item.json}));\n  const messagePerDomain = `<h2>${domaine.toUpperCase().replace(\"-\", \" \")}</h2>${blocMessageSetter(rssList)}`;\n\n  emailHtml += messagePerDomain;\n}\n\nconst object = `Veille tpl-scout \u2014 ${today} (${$input.all().length} ressources)`;\n\nreturn [{json: {emailHtml, object }}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1904,
        -144
      ],
      "id": "8e2bc056-f4db-494e-8c3a-d992f39c8e83",
      "name": "email maker"
    },
    {
      "parameters": {
        "jsCode": "const existing_rss = new Set($('existing rss').all().map(rss => rss.json.lien));\n\nreturn $input.all().filter(rss => !existing_rss.has(rss.json.lien));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        -240
      ],
      "id": "daf4d308-6302-4c02-80c3-05f779465dfd",
      "name": "skip duplication",
      "executeOnce": false,
      "alwaysOutputData": true
    }
  ],
  "connections": {
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "rss links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "rss links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "not empty",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "RSS Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Read": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "rss links": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "filter": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "not empty": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "sucedeed ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "sucedeed ?": {
      "main": [
        [
          {
            "node": "parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "parser": {
      "main": [
        [
          {
            "node": "existing rss",
            "type": "main",
            "index": 0
          },
          {
            "node": "skip duplication",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "new rss ?": {
      "main": [
        [
          {
            "node": "news rss",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "email maker": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "skip duplication": {
      "main": [
        [
          {
            "node": "email maker",
            "type": "main",
            "index": 0
          },
          {
            "node": "new rss ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "7899bb85-058e-491a-8088-08d0d8aabac0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodeGroups": [],
  "id": "6BPSsL8FNqG6s3Hc",
  "tags": []
}