{
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "\ud83c\udf82 Birthday & Anniversary Reminder with AI Gift Ideas \u2014 Telegram",
  "tags": [
    {
      "name": "ai"
    },
    {
      "name": "telegram"
    },
    {
      "name": "reminder"
    },
    {
      "name": "personal"
    }
  ],
  "nodes": [
    {
      "id": "39fe07af-7b6c-413b-bc20-1e034d86d21a",
      "name": "\u23f0 Daily 8 AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        64,
        208
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "731b05eb-b80a-44b7-8baf-83f33adef83d",
      "name": "\u25b6\ufe0f Manual Test",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        64,
        400
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2edf1594-3e7b-4f35-afe5-6537072f6696",
      "name": "\ud83d\udcd6 Read People",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udc46 SETUP: Select your Google Sheet and make sure the tab is named 'People' with columns: name | birthday | relationship | interests",
      "position": [
        352,
        304
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "People"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e00171ba-b535-49a2-a0f3-6021367162cc",
      "name": "\ud83d\udcc5 Check Dates",
      "type": "n8n-nodes-base.code",
      "position": [
        608,
        304
      ],
      "parameters": {
        "jsCode": "// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// CHECK FOR UPCOMING BIRTHDAYS\n// Finds birthdays happening today or within 7 days\n//\n// To change the reminder window, edit the\n// reminderDays variable below (default: 7)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst reminderDays = 7;\nconst people = $input.all();\n\nconst today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst alerts = [];\n\nfor (const item of people) {\n  const p = item.json;\n  if (!p.name || !p.birthday) continue;\n\n  let bday;\n  try {\n    bday = new Date(p.birthday);\n    if (isNaN(bday.getTime())) continue;\n  } catch { continue; }\n\n  const thisYear = new Date(today.getFullYear(), bday.getMonth(), bday.getDate());\n  const nextBday = thisYear < today\n    ? new Date(today.getFullYear() + 1, bday.getMonth(), bday.getDate())\n    : thisYear;\n\n  const daysUntil = Math.round((nextBday - today) / (1000 * 60 * 60 * 24));\n\n  if (daysUntil === 0) {\n    alerts.push({\n      name: p.name,\n      type: 'today',\n      days_until: 0,\n      age: today.getFullYear() - bday.getFullYear(),\n      relationship: p.relationship || 'Contact',\n      interests: p.interests || '',\n      date: nextBday.toISOString().split('T')[0],\n    });\n  } else if (daysUntil === reminderDays) {\n    alerts.push({\n      name: p.name,\n      type: 'upcoming',\n      days_until: daysUntil,\n      age: nextBday.getFullYear() - bday.getFullYear(),\n      relationship: p.relationship || 'Contact',\n      interests: p.interests || '',\n      date: nextBday.toISOString().split('T')[0],\n    });\n  }\n}\n\nif (alerts.length === 0) {\n  return [{ json: { _skip: true } }];\n}\n\nreturn alerts.map(a => ({ json: a }));"
      },
      "typeVersion": 2
    },
    {
      "id": "683c57b9-578f-4d3a-a4d2-d5ac857e2915",
      "name": "\ud83c\udf81 Format Messages",
      "type": "n8n-nodes-base.code",
      "position": [
        864,
        304
      ],
      "parameters": {
        "jsCode": "// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// FORMAT HEADER + BUILD AI PROMPT\n// Creates the notification header and prepares\n// a personalized prompt for the AI model\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const a = item.json;\n\n  if (a._skip) continue;\n  if (!a.name) continue;\n\n  let header = '';\n\n  if (a.type === 'today') {\n    header += `\ud83c\udf82 TODAY \u2014 ${a.name} turns ${a.age}!\\n`;\n    header += `\ud83d\udc64 ${a.relationship}\\n`;\n    header += `\ud83d\udcc5 ${a.date}\\n`;\n  } else {\n    header += `\ud83d\udcc5 REMINDER \u2014 ${a.name}'s birthday in ${a.days_until} days\\n`;\n    header += `\ud83c\udf82 Turning ${a.age} on ${a.date}\\n`;\n    header += `\ud83d\udc64 ${a.relationship}\\n`;\n  }\n\n  if (a.interests) {\n    header += `\ud83d\udca1 Interests: ${a.interests}\\n`;\n  }\n\n  const chatInput = `You are a thoughtful friend. Write a short, warm birthday message (3-4 lines max) for:\\n\\nName: ${a.name}\\nAge: ${a.age}\\nRelationship: ${a.relationship}\\nInterests: ${a.interests || 'not specified'}\\nEvent: ${a.type === 'today' ? 'Birthday is TODAY' : 'Birthday is coming up soon'}\\n\\nAlso suggest 3 personalized gift ideas based on their interests (one line each, with price estimate $20-100).\\n\\nFormat your response EXACTLY like this:\\n\\n\ud83d\udc8c MESSAGE:\\n[your warm message here]\\n\\n\ud83c\udf81 GIFT IDEAS:\\n1. [specific gift] ($XX)\\n2. [specific gift] ($XX)\\n3. [specific gift] ($XX)`;\n\n  results.push({ json: {\n    header: header,\n    chatInput: chatInput,\n    name: a.name,\n  } });\n}\n\nif (results.length === 0) {\n  return [];\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "d22c875c-432d-4a44-b2a9-68cb593ece52",
      "name": "\ud83e\udd16 AI Personalize",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1120,
        304
      ],
      "parameters": {
        "batching": {}
      },
      "typeVersion": 1.9
    },
    {
      "id": "8869ef4d-b0ed-401b-b973-020057f6808b",
      "name": "Groq Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "notes": "\ud83d\udc46 SETUP: Add your Groq API credential (free at console.groq.com)",
      "position": [
        1184,
        528
      ],
      "parameters": {
        "model": "llama-3.1-8b-instant",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "fabb1d2c-5b2d-4dd4-8323-1709a9f4ab2d",
      "name": "\ud83d\udcdd Combine Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1392,
        304
      ],
      "parameters": {
        "jsCode": "// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// COMBINE HEADER + AI RESPONSE\n// Merges the formatted header with AI output\n// into one final Telegram message\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const header = $('\ud83c\udf81 Format Messages').item.json.header || '';\n  const aiResponse = item.json.text || item.json.response || item.json.output || '';\n  \n  const finalMessage = header + '\\n' + aiResponse;\n  \n  results.push({ json: { message: finalMessage } });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "82995885-5700-42ff-8540-4d5553957d43",
      "name": "\ud83d\udcf2 Send Telegram",
      "type": "n8n-nodes-base.telegram",
      "notes": "\ud83d\udc46 SETUP:\n1. Add Telegram credential (token from @BotFather)\n2. Set Chat ID (get yours from @userinfobot)",
      "position": [
        1648,
        304
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "b3b8e08a-dc6f-491d-b625-adccf4753114",
      "name": "Note: Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        -560
      ],
      "parameters": {
        "width": 480,
        "height": 660,
        "content": "## \ud83c\udf82 Birthday & Anniversary Reminder with AI Gift Ideas\n\n### How it works\n1. Runs daily at 8:00 AM (configurable schedule).\n2. Reads a list of people (name, birthday, role, interests) from Google Sheets.\n3. Checks which birthdays or anniversaries are coming up in the next 7 days.\n4. Uses Groq AI (free) to generate 3 personalized gift suggestions per person.\n5. Sends a beautifully formatted reminder with gift ideas to your Telegram.\n\n### Setup steps\n- [ ] Create a Google Sheet with columns: `name`, `birthday` (DD/MM), `role`, `interests`\n- [ ] Create a Telegram bot via @BotFather and get your chat ID from @userinfobot\n- [ ] Get a free Groq API key at [console.groq.com](https://console.groq.com)\n- [ ] Add Groq as an OpenAI credential with base URL `https://api.groq.com/openai/v1`\n- [ ] Connect Google Sheets and Telegram credentials to the workflow nodes\n\n### Customization\n- Change the schedule in the trigger node (default: daily 8 AM)\n- Adjust the lookahead window (default: 7 days) in the Check Dates code node\n- Modify the AI prompt to change gift suggestion style or add budget constraints"
      },
      "typeVersion": 1
    },
    {
      "id": "3dd0f21c-f92b-4660-acb6-fa1ba7ef9ae1",
      "name": "Note: Step 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 296,
        "height": 296,
        "content": "## Step 1: Read Data\n\nReads your people list from Google Sheets.\nRequired columns: `name`, `birthday` (DD/MM), `relationship`, `interests`"
      },
      "typeVersion": 1
    },
    {
      "id": "a30beaf7-0b59-496f-b12b-ad052be94ecd",
      "name": "Note: Step 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 456,
        "height": 296,
        "content": "## Step 2: Check Dates\n\nCompares each person's birthday against today.\nOnly events **today** or **in 7 days** pass through."
      },
      "typeVersion": 1
    },
    {
      "id": "4de74857-d21b-4ca7-8967-ea4b1677c2f3",
      "name": "Note: Step 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 504,
        "content": "## Step 3: AI Gift Ideas (Groq \u2014 Free)\n\nUses Groq LLM to generate a warm birthday message + 3 personalized gift suggestions based on the person's interests. Free at console.groq.com"
      },
      "typeVersion": 1
    },
    {
      "id": "34d3d951-8583-4dd7-af86-fb427afa2e49",
      "name": "Note: Step 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 296,
        "content": "## Step 4: Send Telegram\n\nSends formatted message with birthday info + AI gift ideas. Create a bot via @BotFather, get your chat ID via @userinfobot."
      },
      "typeVersion": 1
    },
    {
      "id": "560024c0-a9a3-4af8-a482-ff25dcb4bdaa",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 448,
        "content": "## Initialize workflow\n\nStarts the workflow."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "connections": {
    "\u23f0 Daily 8 AM": {
      "main": [
        [
          {
            "node": "\ud83d\udcd6 Read People",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "\ud83e\udd16 AI Personalize",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcc5 Check Dates": {
      "main": [
        [
          {
            "node": "\ud83c\udf81 Format Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcd6 Read People": {
      "main": [
        [
          {
            "node": "\ud83d\udcc5 Check Dates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u25b6\ufe0f Manual Test": {
      "main": [
        [
          {
            "node": "\ud83d\udcd6 Read People",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83e\udd16 AI Personalize": {
      "main": [
        [
          {
            "node": "\ud83d\udcdd Combine Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udf81 Format Messages": {
      "main": [
        [
          {
            "node": "\ud83e\udd16 AI Personalize",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcdd Combine Message": {
      "main": [
        [
          {
            "node": "\ud83d\udcf2 Send Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}