Skip to content

Instantly share code, notes, and snippets.

@awsdataarchitect
Created September 1, 2025 04:28
Show Gist options
  • Save awsdataarchitect/3411c2581982c17474d356eb755b3286 to your computer and use it in GitHub Desktop.
Save awsdataarchitect/3411c2581982c17474d356eb755b3286 to your computer and use it in GitHub Desktop.
{
"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