{
  "id": "UzNU7L6PsMjPobQL",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Review your resume against a job description with Gemini and email the report",
  "tags": [],
  "nodes": [
    {
      "id": "50b3d9f1-5ea6-4b07-a794-c8c89cfc6b93",
      "name": "Resume Review Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        48,
        48
      ],
      "parameters": {
        "options": {
          "buttonLabel": "Check my resume",
          "respondWithOptions": {
            "values": {
              "formSubmittedText": "Thanks! Your report is being generated and will arrive by email shortly."
            }
          }
        },
        "formTitle": "Resume vs job description check",
        "formFields": {
          "values": [
            {
              "fieldType": "email",
              "fieldLabel": "Your email",
              "requiredField": true
            },
            {
              "fieldLabel": "Target job title",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Job description",
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "Resume",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".pdf"
            }
          ]
        },
        "formDescription": "Upload your resume and paste the job description. You will get a match score and concrete improvements by email."
      },
      "typeVersion": 2.6
    },
    {
      "id": "b8aea2e4-0006-4993-80bb-d425c0087a99",
      "name": "Extract Resume Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        272,
        48
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "Resume"
      },
      "typeVersion": 1.1
    },
    {
      "id": "94057080-e7cc-413a-a6fe-c09128b4955e",
      "name": "Compare Resume to Job with Gemini",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "onError": "continueErrorOutput",
      "position": [
        608,
        48
      ],
      "parameters": {
        "text": "=You are an experienced recruiter and resume coach. Compare the resume below against the job description and score the match from 0 to 100. Set verdict to \"strong\" when the candidate is clearly a fit, \"partial\" when they could be a fit with edits, and \"weak\" when the gap is large. List the important keywords from the job description that are missing from the resume, the genuine strengths, concrete improvements the candidate should make, and a rewritten professional summary tailored to this role.\n\nTarget role: {{ $('Resume Review Form').item.json['Target job title'] }}\n\nJob description:\n{{ $('Resume Review Form').item.json['Job description'] }}\n\nResume:\n{{ $json.text }}",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "685353ab-e281-45e1-b260-a6e784e36aab",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        576,
        224
      ],
      "parameters": {
        "options": {
          "temperature": 0.2
        },
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "690c5895-7712-4cfa-9008-0baad16ccc96",
      "name": "Match Result Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        816,
        224
      ],
      "parameters": {
        "jsonSchemaExample": "{\"match_score\":78,\"verdict\":\"partial\",\"missing_keywords\":[\"Kubernetes\"],\"strengths\":[\"Strong Python background\"],\"improvements\":[\"Add measurable impact to each role\"],\"rewritten_summary\":\"Backend engineer with 5 years...\"}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e6970c86-18ed-4a55-8031-e713b5610b6a",
      "name": "Parse Match Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1232,
        32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const src = $json.output || $json;\nconst f = $('Resume Review Form').item.json;\nconst join = function (x) { return Array.isArray(x) ? x.join('; ') : (x || ''); };\nconst bullets = function (x) { return Array.isArray(x) ? x.map(function (i) { return '- ' + i; }).join('\\n') : (x || ''); };\nreturn {\n  email: f['Your email'] || '',\n  jobTitle: f['Target job title'] || '',\n  matchScore: Number(src.match_score) || 0,\n  verdict: String(src.verdict || 'partial').toLowerCase(),\n  missingKeywords: join(src.missing_keywords),\n  strengths: join(src.strengths),\n  improvements: join(src.improvements),\n  improvementList: bullets(src.improvements),\n  missingList: bullets(src.missing_keywords),\n  rewrittenSummary: src.rewritten_summary || ''\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "5f0a6c3a-ab9b-4ec0-ace3-c41cac41fa68",
      "name": "Log Review",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1456,
        32
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Resume Reviews"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "767db5fe-3477-494c-aeab-a5df90c587c5",
      "name": "Route by Verdict",
      "type": "n8n-nodes-base.switch",
      "position": [
        1824,
        0
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Match Result\").item.json.verdict }}",
                    "rightValue": "strong"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Match Result\").item.json.verdict }}",
                    "rightValue": "partial"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Match Result\").item.json.verdict }}",
                    "rightValue": "weak"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Other"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "8223f1cc-5bb8-438f-bfef-bc2a05d1a19f",
      "name": "Email Strong Match Report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2064,
        -16
      ],
      "parameters": {
        "sendTo": "={{ $(\"Parse Match Result\").item.json.email }}",
        "message": "={{ \"You are a strong fit for this role - apply now.\\n\\nStrengths:\\n\" + $(\"Parse Match Result\").item.json.strengths + \"\\n\\nPolish these before you send it:\\n\" + $(\"Parse Match Result\").item.json.improvementList + \"\\n\\nSuggested professional summary:\\n\" + $(\"Parse Match Result\").item.json.rewrittenSummary }}",
        "options": {},
        "subject": "={{ \"Strong match (\" + $(\"Parse Match Result\").item.json.matchScore + \"/100) - \" + $(\"Parse Match Result\").item.json.jobTitle }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d70a93ef-6acd-43b1-975d-d18e6a665312",
      "name": "Email Improvement Report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2064,
        160
      ],
      "parameters": {
        "sendTo": "={{ $(\"Parse Match Result\").item.json.email }}",
        "message": "={{ \"You could be a fit with some edits.\\n\\nKeywords the job asks for that your resume is missing:\\n\" + $(\"Parse Match Result\").item.json.missingList + \"\\n\\nDo these before applying:\\n\" + $(\"Parse Match Result\").item.json.improvementList + \"\\n\\nSuggested professional summary:\\n\" + $(\"Parse Match Result\").item.json.rewrittenSummary }}",
        "options": {},
        "subject": "={{ \"Close - \" + $(\"Parse Match Result\").item.json.matchScore + \"/100 for \" + $(\"Parse Match Result\").item.json.jobTitle }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a126b089-b3b1-40da-8b45-3b49b261b18d",
      "name": "Email Rework Plan",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2064,
        336
      ],
      "parameters": {
        "sendTo": "={{ $(\"Parse Match Result\").item.json.email }}",
        "message": "={{ \"This role is a stretch right now, and that is useful to know early.\\n\\nWhat the job wants that you do not show yet:\\n\" + $(\"Parse Match Result\").item.json.missingList + \"\\n\\nHow to close the gap:\\n\" + $(\"Parse Match Result\").item.json.improvementList + \"\\n\\nWhat already works in your favour:\\n\" + $(\"Parse Match Result\").item.json.strengths }}",
        "options": {},
        "subject": "={{ \"Big gap - \" + $(\"Parse Match Result\").item.json.matchScore + \"/100 for \" + $(\"Parse Match Result\").item.json.jobTitle }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "55e63a1d-b828-4f3b-9c17-25a2cd376e94",
      "name": "Email Generic Report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2064,
        512
      ],
      "parameters": {
        "sendTo": "={{ $(\"Parse Match Result\").item.json.email }}",
        "message": "={{ \"Match score: \" + $(\"Parse Match Result\").item.json.matchScore + \"/100\\n\\nStrengths:\\n\" + $(\"Parse Match Result\").item.json.strengths + \"\\n\\nImprovements:\\n\" + $(\"Parse Match Result\").item.json.improvementList }}",
        "options": {},
        "subject": "={{ \"Your resume review - \" + $(\"Parse Match Result\").item.json.jobTitle }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "57d5d280-9960-4f3d-bf32-3ad0ca1a6e49",
      "name": "Email Analysis Failure",
      "type": "n8n-nodes-base.gmail",
      "position": [
        992,
        176
      ],
      "parameters": {
        "sendTo": "={{ $(\"Resume Review Form\").item.json[\"Your email\"] }}",
        "message": "Sorry - we could not read your resume file. Please re-submit a text-based PDF (not a scanned image).",
        "options": {},
        "subject": "We could not analyse your resume",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2e486d9d-897b-40f8-b559-4395a1321ddc",
      "name": "Overview Sticky",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -288
      ],
      "parameters": {
        "width": 440,
        "height": 724,
        "content": "## Review your resume against a job description with Gemini and email the report\n\n### How it works\nMost applications fail because the resume never mirrors the job description. Upload a resume and paste the posting into the built-in n8n form, and a Basic LLM Chain with Google Gemini reads both and returns a 0-100 match score, the keywords the posting asks for that your resume is missing, your genuine strengths, concrete improvements, and a rewritten professional summary tailored to that role. Every review is logged to Google Sheets so you can track applications, and a Switch sends a different email depending on the verdict: strong gets an apply-now nudge, partial gets an edit list, weak gets an honest gap-closing plan.\n\n### Setup\n1. Connect Google Gemini (PaLM) API, Google Sheets and Gmail.\n2. Point the Sheets node at your tracker spreadsheet.\n3. Open the form URL and submit a text-based PDF resume.\n\n### Customization tips\nChange the score bands, or add a second AI call that rewrites the whole resume."
      },
      "typeVersion": 1
    },
    {
      "id": "033264dd-9b24-41a6-af52-660211b26ed2",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 1028,
        "content": "## 1. Submit resume & posting\nThe built-in n8n form collects the email, target role, job description and the resume PDF, then the text is extracted."
      },
      "typeVersion": 1
    },
    {
      "id": "6448fade-776e-4e16-9a86-5476d6519dd0",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        528,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 596,
        "height": 1028,
        "content": "## 2. AI comparison (Basic LLM Chain)\nGemini scores the match and returns missing keywords, strengths, improvements and a tailored summary. Unreadable PDFs trigger an email back."
      },
      "typeVersion": 1
    },
    {
      "id": "7be5b651-6dd7-4595-88c1-bb3fbc859ec3",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 548,
        "height": 1028,
        "content": "## 3. Parse & log\nFlatten the result and append it to your application tracker in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "31343559-416e-4020-83d0-937de9b1e2ca",
      "name": "S4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1728,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 584,
        "height": 1044,
        "content": "## 4. Route by verdict\nStrong gets an apply-now email, partial gets an edit list, weak gets a gap-closing plan, anything unclear gets the generic report."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "babdd4aa-3756-44f9-9c8d-23fb0030f765",
  "nodeGroups": [],
  "connections": {
    "Log Review": {
      "main": [
        [
          {
            "node": "Route by Verdict",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Verdict": {
      "main": [
        [
          {
            "node": "Email Strong Match Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Improvement Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Rework Plan",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Generic Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Match Result": {
      "main": [
        [
          {
            "node": "Log Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resume Review Form": {
      "main": [
        [
          {
            "node": "Extract Resume Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Resume Text": {
      "main": [
        [
          {
            "node": "Compare Resume to Job with Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Result Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Compare Resume to Job with Gemini",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Compare Resume to Job with Gemini",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Compare Resume to Job with Gemini": {
      "main": [
        [
          {
            "node": "Parse Match Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Analysis Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}