{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "48cdb802-0d1d-4458-b54c-477e6596b2c0",
      "name": "JotForm Trigger",
      "type": "n8n-nodes-base.jotFormTrigger",
      "position": [
        -544,
        -224
      ],
      "parameters": {
        "form": "252924486136059",
        "resolveData": false
      },
      "credentials": {
        "jotFormApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "64dd47c3-637e-4c6d-8228-cbca5dd65678",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1536,
        16
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "896b2d2d-f365-43bc-82e3-8f4b69919ce0",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1744,
        16
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"ai_summary\": \"This candidate shows strong experience in B2B SaaS marketing and aligns well with the lead generation responsibilities.\",\n  \"ai_fit_score\": 85,\n  \"key_skills\": [\n    \"B2B SaaS\",\n    \"Lead Generation\",\n    \"HubSpot\",\n    \"SEO\"\n  ]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "99b8801c-6828-4c31-844f-4ae76cd578f3",
      "name": "Download Resume PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        144,
        320
      ],
      "parameters": {
        "url": "={{ $json.uploadYour[0] }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "file"
            }
          }
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth"
      },
      "credentials": {
        "httpQueryAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "37de4b08-9dbf-4365-8a09-1d84076355ee",
      "name": "Read Resume Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        368,
        320
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "cb6ebeb7-c283-42bd-8cb8-f792aebc98b7",
      "name": "Combine Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        944,
        -208
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "915feda6-c102-41f8-9346-940d9e2c1145",
      "name": "Send Confirmation Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        256,
        64
      ],
      "parameters": {
        "sendTo": "={{ $('JotForm Trigger').item.json.q4_email }}",
        "message": "=Hi {{ $('JotForm Trigger').item.json.q3_fullName.first }},\n\nThank you for applying for the {{ $('JotForm Trigger').item.json.q7_positionApplying }} role at IdeaToBiz.\n\nThis email is to confirm we've successfully received your application. Our hiring team will review it, and if your skills and experience are a good match, we'll be in touch.\n\nBest regards,\nThe IdeaToBiz Team",
        "options": {
          "appendAttribution": false
        },
        "subject": "=We've received your application for {{ $('JotForm Trigger').item.json.q7_positionApplying }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "0deab0f1-d6c7-4b40-aa81-88b51dbb6ff9",
      "name": "Alert Hiring Team",
      "type": "n8n-nodes-base.slack",
      "position": [
        2672,
        -224
      ],
      "parameters": {
        "text": "=\ud83d\ude80 *New High-Quality Candidate!*\n\n*Name:* {{ $('JotForm Trigger').item.json.q3_fullName.first }} {{ $('JotForm Trigger').item.json.q3_fullName.last }}\n*Position:* {{ $('JotForm Trigger').item.json.q7_positionApplying }}\n*AI Fit Score:* *{{ $('AI Candidate Analysis').item.json.output.ai_fit_score }}/100*\n*AI Summary:* {{ $('AI Candidate Analysis').item.json.output.ai_summary }}\n\n*View in Notion:*\n{{ $json.url }}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09MC6QEJD9",
          "cachedResultName": "hiring"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "27003e65-79ea-4a91-a387-2aa57b15c072",
      "name": "AI Candidate Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1568,
        -208
      ],
      "parameters": {
        "text": "=You are an expert HR screening assistant. Analyze the candidate's Cover Letter and full Resume Text against the Job Description.\n\nProvide your analysis ONLY in a valid JSON format with three keys:\n1. \"ai_summary\": A 2-sentence summary of the candidate's profile and fit.\n2. \"ai_fit_score\": An integer from 0-100 estimating the candidate's fit for this specific job.\n3. \"key_skills\": An array of strings listing the top 3-5 relevant skills.\n\n**Job Description:**\n{{ $json.property_job_description }}\n\n**Candidate's Cover Letter:**\n{{ $('JotForm Trigger').item.json.q8_typeA8 }}\n\n**Candidate's Full Resume Text:**\n{{ $json.text }}\n",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "8a288c6a-421d-4c16-aad9-0782c1ad42d6",
      "name": "Find Job in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        256,
        -224
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "key": "Name|title",
              "condition": "equals",
              "titleValue": "={{ $json.q7_positionApplying }}"
            }
          ]
        },
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "292a90cb-a525-8082-a905-c52a5cc85703",
          "cachedResultUrl": "https://www.notion.so/292a90cba5258082a905c52a5cc85703",
          "cachedResultName": "Open Positions"
        },
        "filterType": "manual"
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c0ffdabd-7aea-4f66-93c0-524f19397eb5",
      "name": "Score > 40?",
      "type": "n8n-nodes-base.if",
      "position": [
        2160,
        -208
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b2bc439b-3073-4355-843b-60b5ce7dccf9",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.output.ai_fit_score }}",
              "rightValue": 40
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "39de3953-0a8a-4326-bee2-e13b571611c9",
      "name": "Create Candidate in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        2432,
        -224
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "292a90cb-a525-8023-9c07-e106f53923f7",
          "cachedResultUrl": "https://www.notion.so/292a90cba52580239c07e106f53923f7",
          "cachedResultName": "Candidates"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Candidate Name|title",
              "title": "={{ $('JotForm Trigger').item.json.q3_fullName.first }} {{ $('JotForm Trigger').item.json.q3_fullName.last }}"
            },
            {
              "key": "Email|email",
              "emailValue": "={{ $('JotForm Trigger').item.json.q4_email }}"
            },
            {
              "key": "Phone|phone_number",
              "phoneValue": "={{ $('JotForm Trigger').item.json.q5_phoneNumber.full ? $('JotForm Trigger').item.json.q5_phoneNumber.full : null }}"
            },
            {
              "key": "AI Summary|rich_text",
              "textContent": "={{ $json.output.ai_summary }}"
            },
            {
              "key": "AI Fit Score|number",
              "numberValue": "={{ $json.output.ai_fit_score }}"
            },
            {
              "key": "Key Skills|multi_select",
              "multiSelectValue": "={{ $json.output.key_skills }}"
            },
            {
              "key": "Position|relation",
              "relationValue": [
                "={{ $('Find Job in Notion').item.json.id }}"
              ]
            },
            {
              "key": "Resume|files",
              "fileUrls": {
                "fileUrl": [
                  {
                    "url": "={{ $('JotForm Trigger').item.json.uploadYour[0] }}",
                    "name": "=Resume - {{ $('JotForm Trigger').item.json.q3_fullName.first }} {{ $('JotForm Trigger').item.json.q3_fullName.last }}"
                  }
                ]
              }
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "60c22cb8-b24f-4c45-9a1c-f69398e71f9c",
      "name": "Ignore (Score < 40)",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2432,
        -16
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "494e7e12-3f41-4bb0-b181-f869a9a5e75d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -864,
        -1088
      ],
      "parameters": {
        "color": 5,
        "width": 720,
        "height": 1024,
        "content": "## \ud83d\udeaa Configure Your Jotform Form \n\nThis node triggers the workflow when your Jotform is submitted. To work, it requires a specific form setup.\n\nFirst, get your Jotform account:\n[Click here to sign up for Jotform](https://www.jotform.com/?partner=atakhalighi)\n\n### Required Form Fields\nThis template is built to work with a \"Job Application\" form. Your form **must** have the following fields:\n\n1.  **Full Name:** For the candidate's name.\n2.  **Email:** To send the confirmation email.\n3.  **Phone Number:** (Set to 'Optional' in Jotform)\n4.  **File Upload:** For the candidate's resume.\n    * **IMPORTANT:** In the field's options, limit the file type to **`pdf`** to ensure the \"Read Resume Text\" node works.\n5.  **Dropdown:** For the \"Position Applying For.\"\n    * **IMPORTANT:** The options in this dropdown **must exactly match** the `Name` of the pages in your \"Open Positions\" Notion database (e.g., \"Marketing Manager\").\n6.  **Long Text:** For the \"Summary / Cover Letter.\"\n    * **IMPORTANT:** This field is required, as its content is sent to the AI for analysis.\n\n### \u26a0\ufe0f CRITICAL: How to Adapt This Template\nBecause \"Resolve Data\" is turned **OFF** (which is necessary to get the file URL), this template uses Jotform's **Question IDs** (e.g., `q3_fullName`, `q7_positionApplying`).\n\n**Your IDs will be different.** You MUST update them.\n\n### Follow these 3 steps:\n1.  **Submit Your Form:** Run this node once by submitting your *own* test form.\n2.  **Find Your IDs:** Look at the **output** of this node. You will see your own unique IDs (e.g., your \"Position Applying For\" field might be `q5_position`).\n3.  **Update the Workflow:** Go to the downstream nodes (`Find Job in Notion`, `AI Candidate Analysis`, `Create Candidate in Notion`, etc.) and replace **my** Question IDs (like `q7_positionApplying`) with **your** new IDs from the test run."
      },
      "typeVersion": 1
    },
    {
      "id": "d043f3b9-b010-471b-ac6e-ca601c8c6415",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        -752
      ],
      "parameters": {
        "color": 3,
        "width": 752,
        "height": 928,
        "content": "## \ud83e\udde0 The AI Brain (Candidate Analysis)\n\n### What this step does:\nThis is the most powerful step in the workflow! It takes the three key pieces of information we've gathered:\n1.  The **Job Description** (from the `Find Job in Notion` node)\n2.  The **Resume Text** (from the `Read Resume Text` node)\n3.  The **Cover Letter** (from the original `Jotform Trigger`)\n\nIt sends all three to Gemini AI and instructs it to act like an expert HR screener. The AI reads everything and provides a simple, structured JSON output with a summary, a \"fit score,\" and the candidate's key skills.\n\n### Why it's important:\nThis node is what turns your workflow from a simple \"data entry\" tool into a \"decision-making\" tool. It automatically screens every applicant, saving your hiring team hours of work by telling them *which* candidates are a good fit *before* they ever have to open a resume.\n\n### Your To-Do:\n1.  Connect your **Google AI credentials**.\n2.  **CRITICAL:** In the **Prompt** field, you must find the expression that gets the **Cover Letter** text (e.g., `...json.q8_typeA8`). You **must** replace my Question ID (`q8_typeA8`) with the specific Question ID for *your* form's cover letter field. You can find this ID in the output of the first **Jotform Trigger** node."
      },
      "typeVersion": 1
    },
    {
      "id": "ea21c8b2-569b-4066-aacc-4ce80ada8376",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        272
      ],
      "parameters": {
        "color": 4,
        "width": 592,
        "height": 784,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Download and Read the Resume\n\n### Why are these two nodes necessary?\nWhen a user uploads a resume, the Jotform trigger only gives us a **private, secure URL** to the file, *not* the file itself. We need these two steps to securely download that file and then extract the plain text from it so the AI can analyze it.\n\n### How it works:\n1.  **`Download Resume PDF` (HTTP Request):** This node takes the private file URL from the trigger and automatically adds your **Jotform API Key** (which you set up in \"Query Auth\") to the request. This authenticates you and grants permission to download the file. It's set to \"Response Format: File\" to save the raw PDF data.\n\n2.  **`Read Resume Text` (Extract From File):** This node takes the raw PDF data from the previous step, opens it, and extracts all the readable text. This clean text is then passed to the AI.\n\n### Your To-Do:\n1.  Make sure you have created a **Jotform API Key** and added it to the credentials for the `Download Resume PDF` node.\n2.  In the `Download Resume PDF` node's **URL** field, you **must** replace my Question ID (e.g., `uploadYour`) with the file upload ID from *your* form. You can find this ID in the output of the first **Jotform Trigger** node."
      },
      "typeVersion": 1
    },
    {
      "id": "7ce44792-99ab-4fe6-96cb-98b9c172653b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1440,
        -1088
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 1024,
        "content": "## Form Preview\n\n![Job Application Form Preview](https://ideato.biz/storage/2025/10/Job-Application-form.png)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "674c0452-1af6-492b-98a1-4cf950618760",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        -384
      ],
      "parameters": {
        "width": 416,
        "height": 336,
        "content": "### Why:\nThis is a technical node. A simple note explaining, \"This node just waits for the PDF text and the Notion job description to both be ready before sending them to the AI,\" makes the workflow much less intimidating."
      },
      "typeVersion": 1
    },
    {
      "id": "ebf8aa2b-c1cd-4bff-8bce-89539bc9f759",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -704
      ],
      "parameters": {
        "color": 6,
        "width": 800,
        "height": 656,
        "content": "## \ud83c\udfaf Find Job in Notion\n\n### What this step does:\nThis node's job is to search your **\"Open Positions\"** database in Notion. It looks for the specific job page that the candidate applied for (e.g., \"Marketing Manager\").\n\nThis is essential for two reasons:\n1.  It gets the full **Job Description** text, which we need to send to the AI for analysis.\n2.  It gets the **Page ID** of that job, which we'll use in the final step to link the candidate to this specific position.\n\n### Your To-Do (CRITICAL):\n1.  **Select Database:** In the `Database ID` field, click \"Search\" and choose your **\"Open Positions\"** database.\n2.  \u26a0\ufe0f **Update the Filter:** This is the most important part of this node.\n    * Click on **\"Filter\"** to expand it.\n    * In the **Value** field, you will see an expression like `{{ $('Jotform Trigger').item.json.q7_positionApplying }}`.\n    * You **must** delete my Question ID (e.g., `q7_positionApplying`) and replace it with the QID for *your* \"Position Applying For\" dropdown. (You can find your ID in the output of the first **Jotform Trigger** node)."
      },
      "typeVersion": 1
    },
    {
      "id": "866ecfb4-23eb-4de6-ad9e-ca3744e71623",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2880,
        -720
      ],
      "parameters": {
        "color": 5,
        "width": 1632,
        "height": 992,
        "content": "## Final Notion Output Preview\n\n![Job Application Final Notion Output Preview](https://ideato.biz/storage/2025/10/Job-Application-Notion-Output.png)\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Score > 40?": {
      "main": [
        [
          {
            "node": "Create Candidate in Notion",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Ignore (Score < 40)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Data": {
      "main": [
        [
          {
            "node": "AI Candidate Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JotForm Trigger": {
      "main": [
        [
          {
            "node": "Find Job in Notion",
            "type": "main",
            "index": 0
          },
          {
            "node": "Download Resume PDF",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Confirmation Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Resume Text": {
      "main": [
        [
          {
            "node": "Combine Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Find Job in Notion": {
      "main": [
        [
          {
            "node": "Combine Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Resume PDF": {
      "main": [
        [
          {
            "node": "Read Resume Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Candidate Analysis": {
      "main": [
        [
          {
            "node": "Score > 40?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Candidate Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Candidate Analysis",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Create Candidate in Notion": {
      "main": [
        [
          {
            "node": "Alert Hiring Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}