{
  "id": "FhM3j90R33Z2xljk",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "n8n Templates for Upwork",
  "tags": [
    {
      "id": "gXb9aQuVQ6Y8qPJa",
      "name": "upwork",
      "createdAt": "2025-08-29T00:49:12.848Z",
      "updatedAt": "2025-08-29T00:49:12.848Z"
    },
    {
      "id": "iUYtwXp6ROMyrq1Y",
      "name": "proposals",
      "createdAt": "2025-09-04T14:12:54.746Z",
      "updatedAt": "2025-09-04T14:12:54.746Z"
    },
    {
      "id": "wdBKVgVHVo4La799",
      "name": "n8n",
      "createdAt": "2025-08-29T00:49:01.460Z",
      "updatedAt": "2025-08-29T00:49:01.460Z"
    }
  ],
  "nodes": [
    {
      "id": "9eb3a5a6-2981-4052-9433-83bc401c098e",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -240,
        400
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "04ae28c4-4f0b-4a58-8612-a58e7de56a49",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -16,
        400
      ],
      "parameters": {
        "options": {
          "systemMessage": "You are a helpful assistant. \nExtract exactly 5 distinct search keywords or short phrases from the following job description. \nReturn them strictly as a JSON object with the keys \"keyword1\", \"keyword2\", \"keyword3\", \"keyword4\", \"keyword5\". \nDo not include explanations or extra text. \nThe values must be concise search-ready terms taken directly from the job description context."
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0038b249-d5ad-46c5-bbab-119aec8be21f",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        56,
        624
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ace430e0-a890-470c-8926-824d94740e26",
      "name": "Parse Keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        336,
        400
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst updatedItems = items.map((item) => {\n  const output = JSON.parse(item?.json?.output);\n  return output;\n});\nreturn updatedItems;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f847a129-ff2c-4b35-b3f2-bcae45d07707",
      "name": "Search Templates",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1008,
        448
      ],
      "parameters": {
        "url": "https://api.n8n.io/templates/search",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "=search",
              "value": "={{ $json.keyword }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Name",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "f79d297e-6f37-4469-9fa7-c27f4337c4b0",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1008,
        256
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "workflows"
      },
      "typeVersion": 1
    },
    {
      "id": "d9e899bc-3422-42ee-af34-5af6045e5405",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        784,
        400
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "31e957ef-2af1-4482-aad4-7cb86e7445c6",
      "name": "Converting to Array",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        400
      ],
      "parameters": {
        "jsCode": "const input = $json;\nreturn [\n  { json: { keyword: input.keyword1 } },\n  { json: { keyword: input.keyword2 } },\n  { json: { keyword: input.keyword3 } },\n  { json: { keyword: input.keyword4 } },\n  { json: { keyword: input.keyword5 } },\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "3aa34d3e-fe01-4804-a4d4-a629b37d7cdf",
      "name": "Append row in sheet2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1232,
        256
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "={{ $json.id }}",
            "Name": "={{ $json.name }}",
            "User": "={{ $json.user }}",
            "Description": "={{ $json.description }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "User",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "User",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit?usp=drivesdk",
          "cachedResultName": "n8n Projects"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0458e77f-53ea-485f-bde7-90d80c405cf1",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1456,
        256
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.id }}",
              "lookupColumn": "id"
            },
            {
              "lookupValue": "={{ $json.Name }}",
              "lookupColumn": "Name"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit?usp=drivesdk",
          "cachedResultName": "n8n Projects"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1f7e9ea7-88b9-4203-9af8-8c1584f54c4d",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        256
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8c1e234b-030f-4c75-8de2-a10ffcbd3ac3",
              "name": "URL",
              "type": "string",
              "value": "=https://n8n.io/workflows/{{$json.id}}-{{$json.Name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/(^-|-$)/g, \"\")}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "99e6afe4-825e-4e8f-b640-fba60ba35ad6",
      "name": "Update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1904,
        256
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "={{ $json.URL }}",
            "row_number": "={{ $('Get row(s) in sheet').item.json.row_number }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "User",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "User",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1LC7YaRub1nZxdkcrWEt1PtVkZKyy0kcQTXuAv8zlsxY/edit?usp=drivesdk",
          "cachedResultName": "n8n Projects"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ba73d877-d103-4f6c-a09e-63640a817df7",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -144
      ],
      "parameters": {
        "width": 672,
        "height": 384,
        "content": "Title: Setup Instructions\nContent:\n  - Add OpenAI credentials to the LLM node.\n  - Add Google Sheets OAuth credentials to Sheets nodes.\n  - Set GOOGLE_SHEETS_DOC_ID, GOOGLE_SHEET_NAME, and N8N_TEMPLATES_API_URL in \u2699\ufe0f Config.\n  - Create columns: Template ID, Name, User, Description, URL in your Google Sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "48133b53-44f8-4cea-822a-e595ec5ca3a8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        592,
        656
      ],
      "parameters": {
        "color": 5,
        "width": 784,
        "height": 384,
        "content": "Title: Input Trigger\nContent:\n- This node starts the workflow when a chat message is received.\n- The message should contain a job brief or description.\n\nTitle: Keyword Extraction\nContent:\n- The agent extracts 5 distinct keywords from the job description using OpenAI.\n- Output is parsed and converted into an array for further processing.\n\nTitle: Template Search\nContent:\n- For each keyword, the workflow searches the n8n template library API.\n- Results are split and processed individually.\n\nTitle: Google Sheets Logging\nContent:\n- Appends template search results to Google Sheets.\n- Builds a public URL for each template and updates the corresponding row.\n\nTitle: General Notes\nContent:\n- No hardcoded API keys in HTTP nodes.\n- You can swap Google Sheets for Airtable/Notion if needed.\n- Ensure all required columns exist in your destination sheet."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "2ed4f281-7f84-4b36-92cd-2dc00fe2f4af",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Parse Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Append row in sheet2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Update row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Keywords": {
      "main": [
        [
          {
            "node": "Converting to Array",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Search Templates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Templates": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Converting to Array": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet2": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}