Created
September 1, 2025 04:28
-
-
Save awsdataarchitect/3411c2581982c17474d356eb755b3286 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "My workflow", | |
| "nodes": [ | |
| { | |
| "parameters": { | |
| "httpMethod": "POST", | |
| "path": "job-search", | |
| "responseMode": "responseNode", | |
| "options": {} | |
| }, | |
| "id": "5a7399ca-3339-43d6-a960-8c916a45fbdd", | |
| "name": "Webhook Trigger", | |
| "type": "n8n-nodes-base.webhook", | |
| "position": [ | |
| -2336, | |
| -32 | |
| ], | |
| "typeVersion": 2, | |
| "webhookId": "job-hunter-webscraper" | |
| }, | |
| { | |
| "parameters": { | |
| "assignments": { | |
| "assignments": [ | |
| { | |
| "id": "job-title", | |
| "name": "jobTitle", | |
| "type": "string", | |
| "value": "={{ $json.body.jobTitle || 'Software Engineer' }}" | |
| }, | |
| { | |
| "id": "location", | |
| "name": "location", | |
| "type": "string", | |
| "value": "={{ $json.body.location || 'San Francisco, CA' }}" | |
| }, | |
| { | |
| "id": "experience-level", | |
| "name": "experienceLevel", | |
| "type": "string", | |
| "value": "={{ $json.body.experienceLevel || 'Mid-Level' }}" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "id": "e6b3ab8f-6993-419e-9231-88aa3ca06c0e", | |
| "name": "Parse Input", | |
| "type": "n8n-nodes-base.set", | |
| "position": [ | |
| -2144, | |
| -32 | |
| ], | |
| "typeVersion": 3.4 | |
| }, | |
| { | |
| "parameters": { | |
| "zone": { | |
| "__rl": true, | |
| "value": "mcp_unlocker", | |
| "mode": "list", | |
| "cachedResultName": "mcp_unlocker" | |
| }, | |
| "country": { | |
| "__rl": true, | |
| "mode": "list", | |
| "value": "us" | |
| }, | |
| "url": "=https://www.linkedin.com/jobs/search/?keywords={{ encodeURIComponent($json.jobTitle) }}&location={{ encodeURIComponent($json.location) }}&f_TPR=r86400", | |
| "format": "json", | |
| "requestOptions": {} | |
| }, | |
| "id": "97295b11-8c10-48c2-9215-9fb413e1c253", | |
| "name": "LinkedIn Web Unlocker", | |
| "type": "@brightdata/n8n-nodes-brightdata.brightData", | |
| "position": [ | |
| -1952, | |
| -272 | |
| ], | |
| "typeVersion": 1, | |
| "credentials": { | |
| "brightdataApi": { | |
| "id": "YOUR_BRIGHTDATA_CREDENTIAL_ID", | |
| "name": "BrightData account" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Extract job data from LinkedIn HTML with 5-result limit\nconst items = [];\nlet jobCount = 0;\n\nfor (const item of $input.all()) {\n try {\n const html = item.json.body || item.json.data || item.json.content || item.json.html || '';\n \n if (!html || typeof html !== 'string') {\n console.log('No HTML content found, passing through original data');\n items.push(item);\n continue;\n }\n\n // Check if this looks like LinkedIn HTML\n if (html.includes('job-search-card') && html.includes('linkedin.com')) {\n console.log('Processing LinkedIn HTML');\n \n // Extract job listings from HTML using regex patterns\n const jobPattern = /<li>\\s*<div[^>]*class=\"[^\"]*job-search-card[^\"]*\"[^>]*data-entity-urn=\"urn:li:jobPosting:(\\d+)\"[^>]*>[\\s\\S]*?<\\/li>/g;\n const jobs = [];\n let match;\n\n while ((match = jobPattern.exec(html)) !== null && jobCount < 5) {\n const jobHtml = match[0];\n const jobId = match[1];\n \n // Extract job title\n const titleMatch = jobHtml.match(/<h3[^>]*class=\"[^\"]*base-search-card__title[^\"]*\"[^>]*>\\s*([\\s\\S]*?)\\s*<\\/h3>/);\n const title = titleMatch ? titleMatch[1].replace(/<[^>]*>/g, '').trim() : 'Unknown Title';\n \n // Extract company name\n const companyMatch = jobHtml.match(/<h4[^>]*class=\"[^\"]*base-search-card__subtitle[^\"]*\"[^>]*>[\\s\\S]*?<a[^>]*>\\s*([\\s\\S]*?)\\s*<\\/a>/);\n const company = companyMatch ? companyMatch[1].replace(/<[^>]*>/g, '').trim() : 'Unknown Company';\n \n // Extract location\n const locationMatch = jobHtml.match(/<span[^>]*class=\"[^\"]*job-search-card__location[^\"]*\"[^>]*>\\s*([\\s\\S]*?)\\s*<\\/span>/);\n const location = locationMatch ? locationMatch[1].replace(/<[^>]*>/g, '').trim() : 'Unknown Location';\n \n // Extract job URL - More robust extraction\n let jobUrl = '';\n const urlMatch1 = jobHtml.match(/<a[^>]*class=\"[^\"]*base-card__full-link[^\"]*\"[^>]*href=\"([^\"]+)\"/);\n const urlMatch2 = jobHtml.match(/<a[^>]*href=\"([^\"]*\\/jobs\\/view\\/[^\"]+)\"/);\n const urlMatch3 = jobHtml.match(/href=\"(\\/jobs\\/view\\/[^\"]+)\"/);\n \n if (urlMatch1) {\n jobUrl = urlMatch1[1].startsWith('http') ? urlMatch1[1] : `${urlMatch1[1]}`;\n } else if (urlMatch2) {\n jobUrl = urlMatch2[1].startsWith('http') ? urlMatch2[1] : `${urlMatch2[1]}`;\n } else if (urlMatch3) {\n jobUrl = `${urlMatch3[1]}`;\n }\n \n // Extract posting time\n const timeMatch = jobHtml.match(/<time[^>]*datetime=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/time>/);\n const postedDate = timeMatch ? timeMatch[1] : new Date().toISOString().split('T')[0];\n \n jobs.push({\n title: title,\n company: company,\n location: location,\n url: jobUrl,\n job_url: jobUrl,\n description: title,\n salary: 'Not specified',\n postedDate: postedDate,\n sourcePlatform: 'LinkedIn'\n });\n \n jobCount++;\n }\n \n console.log(`Extracted ${jobs.length} jobs from LinkedIn HTML (limited to 5)`);\n \n // Add each job as a separate item\n for (const job of jobs) {\n items.push({ json: job });\n }\n \n } else {\n // Not LinkedIn HTML, pass through original data\n console.log('Not LinkedIn HTML, passing through');\n items.push(item);\n }\n \n } catch (error) {\n console.error('Error extracting job data:', error);\n // Pass through original data on error\n items.push(item);\n }\n}\n\nreturn items;" | |
| }, | |
| "id": "f7722633-1ac5-4820-9baf-4dbb038f5faa", | |
| "name": "Extract HTML Data", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| -1792, | |
| -64 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "assignments": { | |
| "assignments": [ | |
| { | |
| "id": "normalize-title", | |
| "name": "jobTitle", | |
| "type": "string", | |
| "value": "={{ $json.title || $json.job_title || $json.position || 'Unknown Position' }}" | |
| }, | |
| { | |
| "id": "normalize-company", | |
| "name": "companyName", | |
| "type": "string", | |
| "value": "={{ $json.company || $json.company_name || $json.employer || 'Unknown Company' }}" | |
| }, | |
| { | |
| "id": "normalize-location", | |
| "name": "jobLocation", | |
| "type": "string", | |
| "value": "={{ $json.location || $json.job_location || $json.city || 'Unknown Location' }}" | |
| }, | |
| { | |
| "id": "normalize-description", | |
| "name": "description", | |
| "type": "string", | |
| "value": "={{ $json.description || $json.job_description || $json.summary || 'No description available' }}" | |
| }, | |
| { | |
| "id": "normalize-url", | |
| "name": "jobUrl", | |
| "type": "string", | |
| "value": "={{ $json.url || $json.job_url || $json.link || '' }}" | |
| }, | |
| { | |
| "id": "normalize-salary", | |
| "name": "salary", | |
| "type": "string", | |
| "value": "={{ $json.salary || $json.salary_range || $json.compensation || 'Not specified' }}" | |
| }, | |
| { | |
| "id": "source-platform", | |
| "name": "sourcePlatform", | |
| "type": "string", | |
| "value": "LinkedIn" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "id": "9284fc11-e400-4701-875a-ab85b9cbfc63", | |
| "name": "Normalize Data", | |
| "type": "n8n-nodes-base.set", | |
| "position": [ | |
| -1632, | |
| -272 | |
| ], | |
| "typeVersion": 3.4 | |
| }, | |
| { | |
| "parameters": { | |
| "zone": { | |
| "__rl": true, | |
| "value": "mcp_unlocker", | |
| "mode": "list", | |
| "cachedResultName": "mcp_unlocker" | |
| }, | |
| "country": { | |
| "__rl": true, | |
| "mode": "list", | |
| "value": "us" | |
| }, | |
| "url": "={{ $json.jobUrl }}", | |
| "format": "json", | |
| "requestOptions": {} | |
| }, | |
| "id": "e78486fd-9489-404e-b79a-a6a069bdb3e2", | |
| "name": "Job Detail Scraper", | |
| "type": "@brightdata/n8n-nodes-brightdata.brightData", | |
| "position": [ | |
| -1488, | |
| -272 | |
| ], | |
| "typeVersion": 1, | |
| "credentials": { | |
| "brightdataApi": { | |
| "id": "YOUR_BRIGHTDATA_CREDENTIAL_ID", | |
| "name": "BrightData account" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Extract detailed job information and merge with original data\nconst items = [];\nconst normalizeDataOutput = $('Normalize Data').all();\n\nfor (let i = 0; i < $input.all().length; i++) {\n try {\n const item = $input.all()[i];\n const html = item.json.body || item.json.data || item.json.content || item.json.html || '';\n \n // Get corresponding original data from Normalize Data node\n const originalData = normalizeDataOutput[i] ? normalizeDataOutput[i].json : {};\n \n console.log('Original data:', originalData);\n \n if (!html || typeof html !== 'string') {\n // Use normalized data if no HTML\n items.push({\n json: {\n jobTitle: originalData.jobTitle || 'Unknown',\n companyName: originalData.companyName || 'Unknown',\n jobLocation: originalData.jobLocation || 'Unknown',\n description: originalData.description || 'No description',\n jobUrl: originalData.jobUrl || '',\n salary: originalData.salary || 'Not specified',\n sourcePlatform: originalData.sourcePlatform || 'Unknown',\n workType: 'Not specified',\n keySkills: 'Not specified',\n benefits: 'Not specified'\n }\n });\n continue;\n }\n\n // Multiple patterns for job description extraction\n let detailedDescription = originalData.description || 'No description';\n const descPatterns = [\n /<div[^>]*class=\"[^\"]*show-more-less-html__markup[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /<div[^>]*class=\"[^\"]*jobsearch-jobDescriptionText[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /<div[^>]*id=\"jobDescriptionText\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /<section[^>]*class=\"[^\"]*description[^\"]*\"[^>]*>([\\s\\S]*?)<\\/section>/,\n /<div[^>]*class=\"[^\"]*job-description[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/\n ];\n \n for (const pattern of descPatterns) {\n const match = html.match(pattern);\n if (match) {\n detailedDescription = match[1].replace(/<[^>]*>/g, '').trim().substring(0, 1000);\n break;\n }\n }\n \n // Multiple patterns for salary extraction\n let salary = originalData.salary || 'Not specified';\n const salaryPatterns = [\n /<span[^>]*class=\"[^\"]*compensation-text[^\"]*\"[^>]*>([\\s\\S]*?)<\\/span>/,\n /<span[^>]*class=\"[^\"]*salary[^\"]*\"[^>]*>([\\s\\S]*?)<\\/span>/,\n /<div[^>]*class=\"[^\"]*salary-snippet[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /\\$[\\d,]+(?:\\.\\d{2})?(?:\\s*-\\s*\\$[\\d,]+(?:\\.\\d{2})?)?(?:\\s*(?:per|\\/)\\s*(?:hour|year|month))?/i\n ];\n \n for (const pattern of salaryPatterns) {\n const match = html.match(pattern);\n if (match) {\n salary = match[1] ? match[1].replace(/<[^>]*>/g, '').trim() : match[0].trim();\n break;\n }\n }\n \n // Multiple patterns for work type extraction\n let workType = 'Not specified';\n const workTypePatterns = [\n /<span[^>]*class=\"[^\"]*workplace-type[^\"]*\"[^>]*>([\\s\\S]*?)<\\/span>/,\n /<span[^>]*class=\"[^\"]*remote[^\"]*\"[^>]*>([\\s\\S]*?)<\\/span>/,\n /<div[^>]*class=\"[^\"]*work-type[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /\\b(remote|hybrid|on-site|onsite|work from home)\\b/i\n ];\n \n for (const pattern of workTypePatterns) {\n const match = html.match(pattern);\n if (match) {\n workType = match[1] ? match[1].replace(/<[^>]*>/g, '').trim() : match[0].trim();\n break;\n }\n }\n \n // Extract skills and benefits\n let keySkills = [];\n const skillsPatterns = [\n /(?:skills?|technologies?|tools?|requirements?):\\s*([^\\n\\r]{1,200})/i,\n /<div[^>]*class=\"[^\"]*skills[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /<ul[^>]*class=\"[^\"]*skills[^\"]*\"[^>]*>([\\s\\S]*?)<\\/ul>/\n ];\n \n for (const pattern of skillsPatterns) {\n const match = html.match(pattern);\n if (match) {\n const skillsText = match[1].replace(/<[^>]*>/g, '').trim();\n keySkills = skillsText.split(/[,;\\n•]/).map(s => s.trim()).filter(s => s.length > 2).slice(0, 5);\n if (keySkills.length > 0) break;\n }\n }\n \n let benefits = [];\n const benefitsPatterns = [\n /<div[^>]*class=\"[^\"]*benefits[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/,\n /(?:benefits?|perks?):\\s*([^\\n\\r]{1,200})/i,\n /<ul[^>]*class=\"[^\"]*benefits[^\"]*\"[^>]*>([\\s\\S]*?)<\\/ul>/\n ];\n \n for (const pattern of benefitsPatterns) {\n const match = html.match(pattern);\n if (match) {\n const benefitsText = match[1].replace(/<[^>]*>/g, '').trim();\n benefits = benefitsText.split(/[,;\\n•]/).map(b => b.trim()).filter(b => b.length > 2).slice(0, 5);\n if (benefits.length > 0) break;\n }\n }\n \n items.push({\n json: {\n jobTitle: originalData.jobTitle || 'Unknown',\n companyName: originalData.companyName || 'Unknown',\n jobLocation: originalData.jobLocation || 'Unknown',\n description: detailedDescription,\n jobUrl: originalData.jobUrl || '',\n salary: salary,\n sourcePlatform: originalData.sourcePlatform || 'Unknown',\n workType: workType,\n keySkills: keySkills.join(', ') || 'Not specified',\n benefits: benefits.join(', ') || 'Not specified'\n }\n });\n \n } catch (error) {\n console.error('Error extracting job details:', error);\n const originalData = normalizeDataOutput[i] ? normalizeDataOutput[i].json : {};\n items.push({\n json: {\n jobTitle: originalData.jobTitle || 'Unknown',\n companyName: originalData.companyName || 'Unknown',\n jobLocation: originalData.jobLocation || 'Unknown',\n description: originalData.description || 'Error extracting',\n jobUrl: originalData.jobUrl || '',\n salary: originalData.salary || 'Not specified',\n sourcePlatform: originalData.sourcePlatform || 'Unknown',\n workType: 'Not specified',\n keySkills: 'Not specified',\n benefits: 'Not specified'\n }\n });\n }\n}\n\nreturn items;" | |
| }, | |
| "id": "ae6bee08-2596-4217-8c4c-376c9535c236", | |
| "name": "Extract Job Details", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| -1248, | |
| -528 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "model": "us.amazon.nova-premier-v1:0", | |
| "options": { | |
| "temperature": 0.1 | |
| } | |
| }, | |
| "id": "3adc584a-e6b5-40b2-b9a3-4ac9501462cb", | |
| "name": "Nova Premier Agent", | |
| "type": "@n8n/n8n-nodes-langchain.lmChatAwsBedrock", | |
| "position": [ | |
| -1664, | |
| 288 | |
| ], | |
| "typeVersion": 1, | |
| "credentials": { | |
| "aws": { | |
| "id": "YOUR_AWS_CREDENTIAL_ID", | |
| "name": "AWS account" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "promptType": "define", | |
| "text": "=Analyze this job posting and extract detailed information:\n\nJob Title: {{ $json.jobTitle }}\nCompany: {{ $json.companyName }}\nLocation: {{ $json.jobLocation }}\nDescription: {{ $json.description }}\nSalary: {{ $json.salary }}\nSource: {{ $json.sourcePlatform }}\nURL: {{ $json.jobUrl }}\n\nExtract and return ONLY valid JSON with these exact fields:\n{\n \"companyName\": \"exact company name\",\n \"jobTitle\": \"exact job title\",\n \"description\": \"cleaned job description\",\n \"salaryRange\": \"salary information or 'Not specified'\",\n \"location\": \"job location\",\n \"workType\": \"Remote/Hybrid/Onsite/Unknown\",\n \"applicationDeadline\": \"deadline or 'Not specified'\",\n \"recruiterEmail\": \"email if found or 'Not found'\",\n \"hiringManagerEmail\": \"email if found or 'Not found'\",\n \"recruiterLinkedIn\": \"LinkedIn profile if found or 'Not found'\",\n \"benefits\": [\"benefit1\", \"benefit2\"],\n \"keySkills\": [\"skill1\", \"skill2\"],\n \"experienceLevel\": \"Entry/Mid/Senior/Executive\",\n \"jobUrl\": \"{{ $json.jobUrl }}\",\n \"sourcePlatform\": \"{{ $json.sourcePlatform }}\",\n \"extractedAt\": \"{{ new Date().toISOString() }}\"\n}", | |
| "options": { | |
| "systemMessage": "You are an expert recruiter and data extraction specialist. Analyze job postings and extract structured information with high precision. Always return valid JSON only." | |
| } | |
| }, | |
| "id": "a6f28d47-aa6d-40f0-a610-bb54c804a0e2", | |
| "name": "AI Job Analyzer", | |
| "type": "@n8n/n8n-nodes-langchain.agent", | |
| "position": [ | |
| -1040, | |
| -528 | |
| ], | |
| "typeVersion": 2.2, | |
| "executeOnce": true | |
| }, | |
| { | |
| "parameters": { | |
| "mode": "runOnceForEachItem", | |
| "jsCode": "const aiOutput = $json.output;\nlet jobData;\n\ntry {\n const cleanOutput = aiOutput.replace(/```json\\n?/g, '').replace(/\\n?```$/g, '').trim();\n jobData = JSON.parse(cleanOutput);\n} catch (error) {\n jobData = {\n companyName: 'Unknown',\n jobTitle: 'Unknown',\n description: 'Parse error',\n salaryRange: 'Not specified',\n location: 'Unknown',\n workType: 'Unknown',\n applicationDeadline: 'Not specified',\n recruiterEmail: 'Not found',\n hiringManagerEmail: 'Not found',\n recruiterLinkedIn: 'Not found',\n benefits: [],\n keySkills: [],\n experienceLevel: 'Unknown',\n jobUrl: '',\n sourcePlatform: 'Unknown',\n extractedAt: new Date().toISOString()\n };\n}\n\nconst sheetsData = {\n 'Company Name': jobData.companyName || 'Unknown',\n 'Job Title': jobData.jobTitle || 'Unknown',\n 'Location': jobData.location || 'Unknown',\n 'Work Type': jobData.workType || 'Unknown',\n 'Experience Level': jobData.experienceLevel || 'Unknown',\n 'Salary Range': jobData.salaryRange || 'Not specified',\n 'Key Skills': Array.isArray(jobData.keySkills) ? jobData.keySkills.join(', ') : 'Not specified',\n 'Benefits': Array.isArray(jobData.benefits) ? jobData.benefits.join(', ') : 'Not specified',\n 'Recruiter Email': jobData.recruiterEmail || 'Not found',\n 'Hiring Manager Email': jobData.hiringManagerEmail || 'Not found',\n 'Recruiter LinkedIn': jobData.recruiterLinkedIn || 'Not found',\n 'Application Deadline': jobData.applicationDeadline || 'Not specified',\n 'Job URL': jobData.jobUrl || '',\n 'Source Platform': jobData.sourcePlatform || 'Unknown',\n 'Application Status': 'Not Applied',\n 'Priority': 'Medium',\n 'Notes': '',\n 'Extracted At': jobData.extractedAt || new Date().toISOString(),\n 'Cover Letter Generated': 'No',\n 'Cover Letter': '',\n 'Follow Up Date': '',\n 'Interview Scheduled': 'No'\n};\n\nreturn { json: sheetsData };" | |
| }, | |
| "id": "dd7d9e1d-5acc-49ce-ae9c-2ded06598833", | |
| "name": "Structure for Sheets", | |
| "type": "n8n-nodes-base.code", | |
| "position": [ | |
| -1328, | |
| -32 | |
| ], | |
| "typeVersion": 2 | |
| }, | |
| { | |
| "parameters": { | |
| "promptType": "define", | |
| "text": "=Generate a personalized cover letter for this job application:\n\nJob Details:\n- Company: {{ $json['Company Name'] }}\n- Position: {{ $json['Job Title'] }}\n- Location: {{ $json['Location'] }}\n- Key Skills: {{ $json['Key Skills'] }}\n- Benefits: {{ $json['Benefits'] }}\n\nCreate a compelling, professional cover letter that:\n1. Addresses the hiring manager professionally\n2. Shows enthusiasm for the specific role and company\n3. Highlights relevant experience and skills\n4. Demonstrates knowledge of the company/role\n5. Includes a strong call to action\n6. Is concise (3-4 paragraphs)\n\nReturn only the cover letter text, ready to copy and paste.", | |
| "options": { | |
| "systemMessage": "You are an expert career coach. Create personalized, compelling cover letters that help candidates stand out." | |
| } | |
| }, | |
| "id": "d2e3ff6a-43ad-42aa-8055-f55b2db3d260", | |
| "name": "Generate Cover Letter", | |
| "type": "@n8n/n8n-nodes-langchain.agent", | |
| "position": [ | |
| -1312, | |
| 256 | |
| ], | |
| "typeVersion": 2.2, | |
| "alwaysOutputData": false | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Merge all data with generated cover letter\nconst items = [];\nconst sheetsData = $('Structure for Sheets').all();\n\nfor (let i = 0; i < $input.all().length; i++) {\n const coverLetterItem = $input.all()[i];\n const originalSheetData = sheetsData[i] ? sheetsData[i].json : {};\n \n const completeData = {\n ...originalSheetData,\n 'Cover Letter': coverLetterItem.json.output || 'Cover letter generation failed',\n 'Cover Letter Generated': 'Yes'\n };\n \n items.push({ json: completeData });\n}\n\nreturn items;" | |
| }, | |
| "id": "582d9af3-ff9c-4231-a92a-f5a019bc52f6", | |
| "name": "Update Cover Letter", | |
| "type": "n8n-nodes-base.code", | |
| "position": [ | |
| -928, | |
| 176 | |
| ], | |
| "typeVersion": 2 | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "appendOrUpdate", | |
| "documentId": { | |
| "__rl": true, | |
| "value": "YOUR_GOOGLE_SHEET_ID", | |
| "mode": "id" | |
| }, | |
| "sheetName": { | |
| "__rl": true, | |
| "value": "gid=0", | |
| "mode": "list", | |
| "cachedResultName": "Job Applications", | |
| "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0" | |
| }, | |
| "columns": { | |
| "mappingMode": "autoMapInputData", | |
| "value": {}, | |
| "matchingColumns": [ | |
| "Job URL" | |
| ], | |
| "schema": [ | |
| { | |
| "id": "Company Name", | |
| "displayName": "Company Name", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Job Title", | |
| "displayName": "Job Title", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Location", | |
| "displayName": "Location", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Work Type", | |
| "displayName": "Work Type", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Experience Level", | |
| "displayName": "Experience Level", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Salary Range", | |
| "displayName": "Salary Range", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Key Skills", | |
| "displayName": "Key Skills", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Description", | |
| "displayName": "Description", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true, | |
| "removed": false | |
| }, | |
| { | |
| "id": "Benefits", | |
| "displayName": "Benefits", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Recruiter Email", | |
| "displayName": "Recruiter Email", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Hiring Manager Email", | |
| "displayName": "Hiring Manager Email", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Recruiter LinkedIn", | |
| "displayName": "Recruiter LinkedIn", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Application Deadline", | |
| "displayName": "Application Deadline", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Job URL", | |
| "displayName": "Job URL", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true, | |
| "removed": false | |
| }, | |
| { | |
| "id": "Source Platform", | |
| "displayName": "Source Platform", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Application Status", | |
| "displayName": "Application Status", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Priority", | |
| "displayName": "Priority", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Notes", | |
| "displayName": "Notes", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Extracted At", | |
| "displayName": "Extracted At", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Cover Letter Generated", | |
| "displayName": "Cover Letter Generated", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Cover Letter", | |
| "displayName": "Cover Letter", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Follow Up Date", | |
| "displayName": "Follow Up Date", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| }, | |
| { | |
| "id": "Interview Scheduled", | |
| "displayName": "Interview Scheduled", | |
| "required": false, | |
| "defaultMatch": false, | |
| "display": true, | |
| "type": "string", | |
| "canBeUsedToMatch": true | |
| } | |
| ], | |
| "attemptToConvertTypes": false, | |
| "convertFieldsToString": false | |
| }, | |
| "options": {} | |
| }, | |
| "id": "64ea5f15-754f-4274-97fe-a5af841a0cd8", | |
| "name": "Publish to Sheets", | |
| "type": "n8n-nodes-base.googleSheets", | |
| "position": [ | |
| -768, | |
| 240 | |
| ], | |
| "typeVersion": 4.4, | |
| "credentials": { | |
| "googleSheetsOAuth2Api": { | |
| "id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID", | |
| "name": "Google Sheets account" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "respondWith": "json", | |
| "responseBody": "={{ {\n \"status\": \"success\",\n \"message\": \"Job search completed successfully!\",\n \"jobsProcessed\": $input.all().length,\n \"timestamp\": new Date().toISOString(),\n \"summary\": {\n \"totalJobs\": $input.all().length,\n \"coverLettersGenerated\": $input.all().length,\n \"contactsFound\": $input.all().filter(item => item.json['Recruiter Email'] !== 'Not found').length\n }\n} }}", | |
| "options": {} | |
| }, | |
| "id": "ab620ab5-df66-41ff-9078-e70e4e9daf44", | |
| "name": "Send Response", | |
| "type": "n8n-nodes-base.respondToWebhook", | |
| "position": [ | |
| -592, | |
| 256 | |
| ], | |
| "typeVersion": 1.1 | |
| } | |
| ], | |
| "pinData": {}, | |
| "connections": { | |
| "Webhook Trigger": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Parse Input", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse Input": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "LinkedIn Web Unlocker", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "LinkedIn Web Unlocker": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Extract HTML Data", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Extract HTML Data": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Normalize Data", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Normalize Data": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Job Detail Scraper", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Job Detail Scraper": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Extract Job Details", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Extract Job Details": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "AI Job Analyzer", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Nova Premier Agent": { | |
| "ai_languageModel": [ | |
| [ | |
| { | |
| "node": "AI Job Analyzer", | |
| "type": "ai_languageModel", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "Generate Cover Letter", | |
| "type": "ai_languageModel", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "AI Job Analyzer": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Structure for Sheets", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Structure for Sheets": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Generate Cover Letter", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Generate Cover Letter": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Update Cover Letter", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Update Cover Letter": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Publish to Sheets", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Publish to Sheets": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Send Response", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| } | |
| }, | |
| "active": false, | |
| "settings": { | |
| "executionOrder": "v1" | |
| }, | |
| "versionId": "42c46e4c-c3f4-4238-96a2-ecb74257f79b", | |
| "meta": { | |
| "templateCredsSetupCompleted": true, | |
| "instanceId": "b74530c38e67a26aed5e0addf08a2a5d2b483d0f8104bba70627325577c00ffb" | |
| }, | |
| "id": "08wmqE6R5hsTOoSL", | |
| "tags": [ | |
| { | |
| "createdAt": "2025-08-31T01:40:07.565Z", | |
| "updatedAt": "2025-08-31T01:40:07.565Z", | |
| "id": "3VWo9WOq8dc04WWn", | |
| "name": "AI Agent" | |
| }, | |
| { | |
| "createdAt": "2025-08-31T01:40:07.588Z", | |
| "updatedAt": "2025-08-31T01:40:07.588Z", | |
| "id": "ip68R2RvcnKzuFbc", | |
| "name": "Job Automation" | |
| }, | |
| { | |
| "createdAt": "2025-08-31T01:40:07.537Z", | |
| "updatedAt": "2025-08-31T01:40:07.537Z", | |
| "id": "zzj9ZECkWoL93yaq", | |
| "name": "BrightData" | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment