{
  "name": "Weekly Real Estate 12-Pack (Sunday 10am ET)",
  "nodes": [
    {
      "id": "CronWeekly",
      "name": "Weekly (Sunday 10:00 AM)",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 2,
      "position": [
        260,
        300
      ],
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyWeek",
              "hour": 10,
              "minute": 0,
              "weekday": "sunday"
            }
          ]
        },
        "timezone": "America/Indiana/Indianapolis"
      }
    },
    {
      "id": "SetFeeds",
      "name": "Set Feeds",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        520,
        300
      ],
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "feeds",
              "value": "https://indianapolis.craigslist.org/search/rea?format=rss\nhttps://YOUR-SECOND-FEED-URL-HERE\nhttps://YOUR-THIRD-FEED-URL-HERE"
            },
            {
              "name": "email_subject",
              "value": "\ud83c\udfe0 Weekly 12 New Listings \u2014 {{new Date().toLocaleDateString('en-US')}}"
            }
          ],
          "number": [
            {
              "name": "maxItems",
              "value": 12
            }
          ]
        }
      }
    },
    {
      "id": "SplitFeeds",
      "name": "Split Feeds",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        780,
        300
      ],
      "parameters": {
        "batchSize": 1
      }
    },
    {
      "id": "RSSRead",
      "name": "RSS Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [
        1020,
        300
      ],
      "parameters": {
        "url": "={{$json.feeds.split('\\n')[$items('Split Feeds').index]}}",
        "options": {
          "includeFullContent": true
        }
      }
    },
    {
      "id": "MergeAll",
      "name": "Merge All",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 2,
      "position": [
        1240,
        300
      ],
      "parameters": {
        "mode": "append"
      }
    },
    {
      "id": "HasMoreFeeds?",
      "name": "Has More Feeds?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1240,
        480
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$items('Split Feeds').continue}}",
              "operation": "isTrue"
            }
          ]
        }
      }
    },
    {
      "id": "ContinueBatches",
      "name": "Next Feed",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1020,
        480
      ]
    },
    {
      "id": "SelectTop12AndHTML",
      "name": "Select Top 12 + Build HTML",
      "type": "n8n-nodes-base.function",
      "typeVersion": 2,
      "position": [
        1480,
        300
      ],
      "parameters": {
        "functionCode": "const max = $json.maxItems || 12;\n// Flatten all incoming items from Merge All\nlet items = [];\nfor (const input of $input.all()) {\n  if (Array.isArray(input.json)) {\n    items.push(...input.json);\n  } else {\n    items.push(input.json);\n  }\n}\n// Normalize fields\nconst parsed = items.map(it => {\n  const title = it.title || it['content:encoded']?.title || 'Untitled';\n  const link = it.link || it.guid || '#';\n  const pub = new Date(it.isoDate || it.pubDate || it.date || 0).getTime();\n  const priceMatch = /\\$[0-9,]+/i.exec(title + ' ' + (it.contentSnippet || ''));\n  let image = undefined;\n  if (it.enclosure && it.enclosure.url) image = it.enclosure.url;\n  // try to pull first image from content\n  const html = (it['content:encoded'] || it.content || '');\n  const imgMatch = /<img[^>]+src=[\"']([^\"']+)[\"']/i.exec(html);\n  if (!image && imgMatch) image = imgMatch[1];\n  return {\n    title,\n    link,\n    date: pub || 0,\n    price: priceMatch ? priceMatch[0] : '',\n    summary: (it.contentSnippet || '').slice(0, 200),\n    image\n  };\n});\n// Sort newest first\nparsed.sort((a,b)=>b.date - a.date);\n// Take top N\nconst top = parsed.slice(0, max);\n\n// Build simple responsive email HTML\nconst css = `\n  body{font-family:Arial,Helvetica,sans-serif;margin:0;padding:0;background:#f6f7fb}\n  .wrap{max-width:720px;margin:0 auto;padding:24px}\n  h1{font-size:20px;margin:0 0 16px}\n  .grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}\n  .card{background:#fff;border:1px solid #e5e7eb;border-radius:10px;overflow:hidden}\n  .img{width:100%;height:160px;object-fit:cover;background:#eee}\n  .pad{padding:12px}\n  .title{font-size:15px;margin:0 0 6px}\n  .meta{color:#6b7280;font-size:12px;margin:0 0 8px}\n  a.btn{display:inline-block;margin-top:8px;padding:8px 12px;border-radius:8px;border:1px solid #111;text-decoration:none;color:#111}\n`;\nlet cards = top.map((p,i)=>{\n  const dt = p.date ? new Date(p.date).toLocaleDateString('en-US') : '';\n  return `\n    <div class=\"card\">\n      ${p.image ? `<img class=\"img\" src=\"${p.image}\" alt=\"Listing image\"/>` : ''}\n      <div class=\"pad\">\n        <h3 class=\"title\">${p.title.replace(/</g,'&lt;')}</h3>\n        <p class=\"meta\">${p.price} ${dt? ' \u2022 ' + dt: ''}</p>\n        <p>${(p.summary||'').replace(/</g,'&lt;')}...</p>\n        <a class=\"btn\" href=\"${p.link}\" target=\"_blank\" rel=\"noopener\">View Listing</a>\n      </div>\n    </div>`;\n}).join('');\n\nif (!cards) cards = '<p>No fresh listings found this week.</p>';\n\nconst html = `<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/><style>${css}</style></head><body><div class=\"wrap\"><h1>${$json.email_subject || 'Weekly Listings'}</h1><div class=\"grid\">${cards}</div><p style=\"color:#6b7280;font-size:12px;margin-top:16px\">You are receiving this because you subscribed to weekly listings. Unsubscribe any time.</p></div></body></html>`;\n\nreturn [{ json: { html, count: top.length } }];"
      }
    },
    {
      "id": "EmailSend",
      "name": "Email Send (SMTP)",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        1720,
        300
      ],
      "parameters": {
        "fromEmail": "you@yourdomain.com",
        "toEmail": "test@example.com",
        "subject": "={{$json.email_subject}}",
        "options": {
          "allowUnauthorizedCerts": false,
          "ignoreSslIssues": false,
          "convertTextToHtml": false,
          "binaryPropertyName": ""
        },
        "html": "={{$json.html}}"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "NotifyYou",
      "name": "Notify (Success Log)",
      "type": "n8n-nodes-base.function",
      "typeVersion": 2,
      "position": [
        1940,
        300
      ],
      "parameters": {
        "functionCode": "console.log(`Sent weekly real estate email with ${$json.count} items.`);\nreturn items;"
      }
    }
  ],
  "connections": {
    "Weekly (Sunday 10:00 AM)": {
      "main": [
        [
          {
            "node": "Set Feeds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Feeds": {
      "main": [
        [
          {
            "node": "Split Feeds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Feeds": {
      "main": [
        [
          {
            "node": "RSS Read",
            "type": "main",
            "index": 0
          }
        ]
      ],
      "next": [
        [
          {
            "node": "ContinueBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Read": {
      "main": [
        [
          {
            "node": "Merge All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ContinueBatches": {
      "main": [
        [
          {
            "node": "Has More Feeds?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All": {
      "main": [
        [
          {
            "node": "Has More Feeds?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has More Feeds?": {
      "main": [
        [
          {
            "node": "Split Feeds",
            "type": "next",
            "index": 0
          }
        ],
        [
          {
            "node": "Select Top 12 + Build HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Top 12 + Build HTML": {
      "main": [
        [
          {
            "node": "Email Send (SMTP)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Send (SMTP)": {
      "main": [
        [
          {
            "node": "Notify (Success Log)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "all",
    "timezone": "America/Indiana/Indianapolis"
  },
  "versionId": "weekly-real-estate-12pack-v1"
}