{
  "name": "03 Remote jobs -> Google Sheet + alert",
  "nodes": [
    {
      "parameters": {
        "content": "## Remote jobs feed\nEvery 12h pulls fresh remote jobs from 8 boards for your keywords, appends them to a Google Sheet and sends a summary.\nConnect Google Sheets credentials in the sheet node.\n\n1. Open **Config** and paste your Apify API token (free account: console.apify.com -> Settings -> API & Integrations).\n2. Paste a Discord/Slack webhook URL and/or a Telegram bot token + chat ID (delete the node you don't use).\n3. Click **Test workflow**, then switch it to **Active**.",
        "height": 340,
        "width": 420
      },
      "name": "How to use",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -400
      ],
      "id": "d24870f3-868d-4e5a-a846-7b00be93fbdc"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 12
            }
          ]
        }
      },
      "name": "Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "id": "043b4b9e-7dbf-43f7-a793-7507abc6dca7"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "086ea72e-0cfd-48be-ab06-6dacc0201baf",
              "name": "apifyToken",
              "value": "YOUR_APIFY_TOKEN",
              "type": "string"
            },
            {
              "id": "5b94103f-bb25-4ffb-a40b-d4f5b8aecdd1",
              "name": "webhookUrl",
              "value": "https://discord.com/api/webhooks/...",
              "type": "string"
            },
            {
              "id": "7f77fce2-2a86-4ff7-8dcd-e839c491966a",
              "name": "telegramBotToken",
              "value": "",
              "type": "string"
            },
            {
              "id": "2481db6e-e242-43f5-b138-e5253f52cfa5",
              "name": "telegramChatId",
              "value": "",
              "type": "string"
            },
            {
              "id": "9a73b440-5158-4e12-8720-82dfe7ebe3a2",
              "name": "keywords",
              "value": "python, data engineer",
              "type": "string"
            },
            {
              "id": "9909f659-6035-4da6-bde8-95d5ba771750",
              "name": "googleSheetUrl",
              "value": "https://docs.google.com/spreadsheets/d/...",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ],
      "id": "4af90652-85ec-45ea-be75-9cfd0c66b101"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.apify.com/v2/acts/martin10291~remote-jobs-aggregator-pro/run-sync-get-dataset-items",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "token",
              "value": "={{ $('Config').item.json.apifyToken }}"
            },
            {
              "name": "timeout",
              "value": "280"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({searchQueries: $('Config').item.json.keywords.split(',').map(s => s.trim()), maxItems: 50, postedWithinDays: 1}) }}",
        "options": {
          "timeout": 300000
        }
      },
      "name": "Run Apify scraper",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        0
      ],
      "id": "053bdc3e-f53a-4d2f-97cb-dc880f94dab2"
    },
    {
      "parameters": {
        "jsCode": "const rows = $input.all();\nreturn rows.map(i => ({ json: { title: i.json.title, company: i.json.company, location: i.json.location, salary: [i.json.salaryMin, i.json.salaryMax].filter(Boolean).join('-') + (i.json.salaryCurrency ? ' ' + i.json.salaryCurrency : ''), source: i.json.source, url: i.json.applyUrl || i.json.url, postedAt: i.json.postedAt } }));"
      },
      "name": "Pick columns",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ],
      "id": "b9c7a644-cd7d-450e-a57d-f8537634f402"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Config').item.json.googleSheetUrl }}"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {}
        },
        "options": {}
      },
      "name": "Append to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        880,
        0
      ],
      "id": "6a3c3a40-8fab-4590-a436-acbc39f7a93d"
    },
    {
      "parameters": {
        "jsCode": "const rows = $input.all();\nif (!rows.length) return [];\nconst t = 'New remote jobs:\\n' + rows.slice(0, 15).map(i => `• ${i.json.title} @ ${i.json.company}\\n${i.json.url}`).join('\\n');\nreturn [{ json: { text: t } }];"
      },
      "name": "Format message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        200
      ],
      "id": "942adda5-b61a-41d8-b611-71340fb38a5c"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Config').item.json.webhookUrl }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({content: $json.text, text: $json.text}) }}",
        "options": {}
      },
      "name": "Send to Discord or Slack",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1100,
        200
      ],
      "id": "668a1baf-b594-447c-a757-c58561d24985"
    }
  ],
  "connections": {
    "Schedule": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Run Apify scraper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Apify scraper": {
      "main": [
        [
          {
            "node": "Pick columns",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick columns": {
      "main": [
        [
          {
            "node": "Append to Google Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format message": {
      "main": [
        [
          {
            "node": "Send to Discord or Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "active": false
}