{
  "id": "OMGFOlTIKsAAAwUG",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Spotify Emotion-to-News Card Generator (APITemplate.io + Slack)",
  "tags": [],
  "nodes": [
    {
      "id": "773130e9-c130-4276-b4f5-6fa0cd79ba91",
      "name": "Emotion Analyzer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        304,
        -16
      ],
      "parameters": {
        "text": "=You are an emotion analyst.\nGiven the following song title and artist, infer the main emotion it conveys \n(e.g., joyful, nostalgic, melancholic, energetic, angry, romantic).\nReturn JSON.\n\nInput:\n\"{{ $json.track.name }} - {{ $json.track.album.artists[0].name }}\"\n\nOutput:\n{\n  \"emotion\": \"nostalgic\",\n  \"reason\": \"The song's tone and lyrics evoke reflection and memory.\"\n}\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "734a0e4f-1a01-4bfd-8877-4629ef89d1a4",
      "name": "Start on Schedule (Cron)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -144,
        -16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3c9cf5ff-747e-436c-b47d-8d55b2fdde40",
      "name": "Fetch Spotify Recently Played",
      "type": "n8n-nodes-base.spotify",
      "position": [
        80,
        -16
      ],
      "parameters": {
        "operation": "recentlyPlayed"
      },
      "credentials": {
        "spotifyOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e051c66b-fdfb-4ef7-860a-9a14c9c29f9e",
      "name": "LLM: Infer Emotion from Track",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        384,
        208
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ee6e19e5-8843-4669-87e6-432d0c944db7",
      "name": "For Each Track (Batch)",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        656,
        -16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "282fbf38-97c2-4510-bed4-08072dea9f71",
      "name": "Build Google News RSS Query",
      "type": "n8n-nodes-base.set",
      "position": [
        880,
        -16
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{\n  (() => {\n    const raw =\n      $json.emotion ||\n      (JSON.parse($json.output || '{}').emotion) ||\n      'music';\n    const clean = String(raw).replace(/\\s+/g,' ').replace(/\\u3000/g,' ').trim();\n    const base = 'https://news.google.com/rss/search?hl=en-US&gl=US&ceid=US%3Aen&q=';\n    return { feedUrl: base + encodeURIComponent(clean) }; // \u2190 \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3067\u8fd4\u3059\n  })()\n}}\n"
      },
      "typeVersion": 3.4
    },
    {
      "id": "1636d83b-5ff3-4360-b70c-c469691e7d15",
      "name": "Fetch Google News RSS",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1104,
        -16
      ],
      "parameters": {
        "url": "={{\n  (() => {\n    const emotionRaw =\n      $json.emotion ||\n      (JSON.parse($json.output || '{}').emotion) ||\n      'music';\n\n    const q = encodeURIComponent(String(emotionRaw).trim());\n    const url = `https://news.google.com/rss/search?hl=en-US&gl=US&ceid=US%3Aen&q=${q}`;\n    return url.trim();\n  })()\n}}\n",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "89aab605-b6bb-4206-8866-c6bb97f269e5",
      "name": "Pick Top News & Format",
      "type": "n8n-nodes-base.code",
      "position": [
        1328,
        -16
      ],
      "parameters": {
        "jsCode": "return items.slice(0, 1);"
      },
      "typeVersion": 2
    },
    {
      "id": "20707f6c-fbec-45a8-94e0-a42574e9c90e",
      "name": "Generate News Card (APITemplate)",
      "type": "n8n-nodes-base.apiTemplateIo",
      "position": [
        1552,
        -16
      ],
      "parameters": {
        "overridesJson": "={{ JSON.stringify([\n  { \"name\": \"text_emotion\", \"text\": $json.emotion ?? \"neutral\" },\n  { \"name\": \"text_url\",     \"text\": $json.link ?? \"https://example.com\" },\n  { \"name\": \"text_1\",       \"text\": $json.contentSnippet ?? \"Unknown source\" },\n  { \"name\": \"text_2\",       \"text\": $json.title ?? \"No title\" }\n]) }}\n",
        "jsonParameters": true,
        "imageTemplateId": "="
      },
      "credentials": {
        "apiTemplateIoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "abed781e-894c-4239-8f89-34532fe17022",
      "name": "Post to Slack (Title + Link + Card URL)",
      "type": "n8n-nodes-base.slack",
      "position": [
        1776,
        -16
      ],
      "parameters": {
        "text": "={{\n  $(\"Pick Top News & Format\").item.json.title + \"\\n\" +\n  $(\"Pick Top News & Format\").item.json.link + \"\\n\" +\n  \"\ud83d\udcf0 \u30cb\u30e5\u30fc\u30b9\u30ab\u30fc\u30c9\\n\" +\n  ( $(\"Generate News Card (APITemplate)\").item.json.download_url_png || $(\"Generate News Card (APITemplate)\").item.json.download_url )\n}}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "CKUCBTG0H",
          "cachedResultName": "general"
        },
        "otherOptions": {
          "unfurl_links": false,
          "unfurl_media": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "259a3bb9-d297-442c-b998-ea7aed02d1d1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        -352
      ],
      "parameters": {
        "width": 416,
        "height": 1344,
        "content": "## \ud83d\udcc4 Workflow Overview\n\nTitle: Spotify Emotion-to-News Card Generator (APITemplate.io + Slack)\n\n## What it does:\nThis workflow analyzes the emotion of your recently played Spotify track using OpenRouter (LLM), fetches a related trending Google News article, generates a visual news card with APITemplate.io, and posts it to Slack.\n\n## \ud83d\udc65 Who\u2019s it for\n\nMusic lovers, marketers, and developers who want to automatically turn their listening mood into a visual daily digest or Slack update.\n\n## \u2699\ufe0f How it works\n\nSpotify Trigger \u2014 Fetch your recently played tracks.\n\nLLM (Emotion Analyzer) \u2014 Infer the main emotion from the track title and artist.\n\nGoogle News Query \u2014 Build an RSS URL based on the emotion keyword.\n\nRSS Reader \u2014 Retrieve trending news headlines.\n\nAPITemplate.io \u2014 Render the top article into an image card.\n\nSlack \u2014 Post title, link, and card image into your channel.\n\n## \ud83e\uddf0 Requirements\n\nSpotify API credentials\n\nOpenRouter API key\n\nAPITemplate.io account (with template ID)\n\nSlack OAuth2 connection\n\n## \ud83e\ude84 How to customize\n\nReplace the APITemplate.io template ID with your own.\n\nAdjust the RSS URL language (hl=en-US \u2192 hl=ja-JP for Japanese news).\n\nModify the Slack message text for your preferred channel tone.\n\n## \u26a0\ufe0f Disclaimer\n\nIf you use community nodes (LangChain), this template is for self-hosted n8n only."
      },
      "typeVersion": 1
    },
    {
      "id": "930501ea-23fc-4014-b2e1-8547d609680e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        -240
      ],
      "parameters": {
        "color": 7,
        "content": "## Start on Schedule (Cron)\n\u201cTriggers this workflow on a fixed schedule. You can adjust interval in node settings.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "4b84f0fc-1f3f-4ebf-934e-3092759aae9f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        192
      ],
      "parameters": {
        "color": 7,
        "height": 176,
        "content": "## Fetch Spotify Recently Played\n\u201cRetrieves your last played Spotify tracks. Requires Spotify OAuth2 credentials.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "8fe180e8-594c-470b-9b1d-fa754582ae19",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        -208
      ],
      "parameters": {
        "color": 7,
        "height": 128,
        "content": "## Emotion Analyzer\n\u201cUses LLM (OpenRouter) to infer the dominant emotion from song title and artist.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "7017bd67-3219-492c-9334-16883310c843",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        160
      ],
      "parameters": {
        "color": 7,
        "height": 176,
        "content": "## For Each Track (Batch)\n\u201cProcesses each track individually for emotion-to-news mapping.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "c0ad00c2-c320-41c2-ad1e-982c192fc81c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        -256
      ],
      "parameters": {
        "color": 7,
        "height": 176,
        "content": "## Build Google News RSS Query\n\u201cConverts emotion into a Google News RSS query string. Modify hl and gl for language/country.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "ab9563f1-d47a-49fc-ba02-149b251e8a0e",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        160
      ],
      "parameters": {
        "color": 7,
        "content": "## Fetch Google News RSS\n\u201cReads top articles matching the emotion keyword.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "1d92ea4b-bba2-4be9-8401-1174cbefef9a",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        -240
      ],
      "parameters": {
        "color": 7,
        "content": "## Pick Top News & Format\n\u201cSelects the first article from RSS feed and prepares title/link/snippet.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "afe292e6-24aa-42c8-9de5-e1d78b7acf30",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        176
      ],
      "parameters": {
        "color": 7,
        "height": 208,
        "content": "## Generate News Card (APITemplate)\n\u201cCreates a news card image using APITemplate.io. Replace template ID with yours.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "9914e9fa-6135-40ce-abf3-053a3c798c03",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        -208
      ],
      "parameters": {
        "color": 7,
        "content": "## Post to Slack (Title + Link + Card URL)\n\u201cPosts the generated card, title, and link to Slack. Unfurling disabled for clean appearance.\u201d"
      },
      "typeVersion": 1
    },
    {
      "id": "842092ca-795b-4330-b1c8-b83b6c8652e8",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 752,
        "content": "## Setup (Step-by-Step)\n\nGoal: Analyze your recent Spotify listening history, infer the emotional tone, and generate a matching news image card that\u2019s automatically posted to Slack.\nPrerequisites: n8n (Cloud or Self-hosted), and active accounts for Spotify, Slack, APITemplate.io, and OpenRouter.\n\n1) Create Credentials (Required)\n\nSpotify OAuth2 \u2014 Go to Settings \u2192 Credentials \u2192 New \u2192 Spotify OAuth2, create a credential, and assign it to the \u201cFetch Spotify Recently Played\u201d node.\n\nSlack OAuth2 \u2014 Create it under Settings \u2192 Credentials, and assign it to \u201cPost to Slack.\u201d\n\nAPITemplate.io \u2014 Create it under Settings \u2192 Credentials, and assign it to \u201cGenerate News Card (APITemplate).\u201d\n\nOpenRouter API (LLM) \u2014 Create it under Settings \u2192 Credentials, and assign it to \u201cInfer Emotion from Track (LLM).\u201d\nIf you\u2019re concerned about Cloud compatibility, refer to the \u201cSelf-host / Cloud\u201d alternative described below."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b0b1e713-4148-491c-ba26-71d4520280bf",
  "connections": {
    "Emotion Analyzer": {
      "main": [
        [
          {
            "node": "For Each Track (Batch)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google News RSS": {
      "main": [
        [
          {
            "node": "Pick Top News & Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "For Each Track (Batch)": {
      "main": [
        [],
        [
          {
            "node": "Build Google News RSS Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick Top News & Format": {
      "main": [
        [
          {
            "node": "Generate News Card (APITemplate)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start on Schedule (Cron)": {
      "main": [
        [
          {
            "node": "Fetch Spotify Recently Played",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Google News RSS Query": {
      "main": [
        [
          {
            "node": "Fetch Google News RSS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Spotify Recently Played": {
      "main": [
        [
          {
            "node": "Emotion Analyzer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM: Infer Emotion from Track": {
      "ai_languageModel": [
        [
          {
            "node": "Emotion Analyzer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate News Card (APITemplate)": {
      "main": [
        [
          {
            "node": "Post to Slack (Title + Link + Card URL)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Slack (Title + Link + Card URL)": {
      "main": [
        []
      ]
    }
  }
}