Huashu Design
alchaincyf · Skill
Turns a one-line request in your AI agent into a finished design: a launch animation, a clickable app prototype, an editable slide deck, an infographic or a se…
An n8n workflow that keeps every job applicant in one Google Sheet. A new email adds a row, with OpenAI reading the job title from the subject. Forms, sheet edits and Cal.com bookings then fill in screening, a task and an interview, and Gmail writes to the candidate.
Job applicant pipeline tracker in Google Sheets is an n8n workflow in the Business category, listed by Mindket. It is free. This is version 1, last updated on . Download it on this page or copy its JSON, then import it into an n8n canvas. Nothing runs until you activate it in n8n.
Five triggers
It starts from five places: a Gmail check every hour, the two forms, a sheet-edit webhook and a Cal.com booking. The onboarding form asks for:
One sheet row for each candidate, showing how far they have got, with an email sent at each step you choose
What you need before you start.
Finds new applicant mail and sends the follow-up emails from your own account.
NeedsA Google account that may read and send mail
Spreadsheet
Holds one row for each candidate, and the application, both forms and the booking update it.
NeedsA Google account with Sheets access, and a sheet with the 20 columns
Language model
Reads the job title out of each subject line with gpt-4o-mini and answers as JSON.
NeedsOpenAI API key
Scheduling
Tells the workflow when a candidate books an interview, with the code they were given.
NeedsCal.com API key
Checked by Mindket on 13 Nov 2026
This n8n workflow follows a job applicant from the first email to a booked interview, all in one Google Sheet. Its 16 nodes make five lanes, and each lane has its own trigger. Each lane stands alone. Gmail checks for new mail every hour, and OpenAI reads the job title out of the subject. The sheet gets a row with the sender’s name and address, the job, a date and a random code, and a first email goes out. The code is how the other lanes find that row again. An onboarding form asks the candidate for it, a task form asks for it, and Cal.com carries it in a booking answer. A separate lane listens for your edits in the sheet and emails the candidate when you mark Screening, Rejected or Test approved.
Small teams that hire a few people by email and want a record that is not an inbox: founders, office managers and freelance recruiters. Skip it for volume hiring or anything that needs permissions. Nothing checks that the person typing a code owns it. The sheet is only as private as its sharing settings.
| Industry | Who uses it | How they use it | Example |
|---|---|---|---|
| Small business | Owners who hire a few people a year | Keep every applicant, task and interview in one sheet | A café owner sees at a glance who has not sent the task yet. |
| Recruiting | Freelance recruiters | Run one sheet per client and tick a column to send each update | A recruiter ticks Screening on three rows and three candidates get their next email. |
| Startups | Founders and operations leads | Let the forms and the booking fill the sheet, so the team only decides | A founder opens the sheet on Monday and sees who has booked an interview. |
| Studios and agencies | Hiring managers for design or development roles | Ask for a take-home task and collect its link in Test Link | A studio reads each candidate’s link in the sheet and ticks Test Approved. |
Any n8n that can reach Gmail, OpenAI, Google Sheets and Cal.com will run it. The sheet is the board. Your team works there, not in n8n.
codeGet it saves a zip with workflow.json and Mindket’s setup notes in your downloads folder. Its author puts setup at about 16 minutes. The four Gmail nodes arrive with no subject and no message, so you write those yourself.
| Need | Detail |
|---|---|
| n8n | On n8n Cloud or on a server of your own |
| An account for Gmail and Google Sheets, with an OAuth2 credential for each | |
| OpenAI | An API key. One node uses it, OpenAI |
| Cal.com | An account and its API key |
| A spreadsheet | 20 columns named in the README, with Code in column S |
| Apps Script | A short script in the spreadsheet that posts your edits to Webhook |
workflow.json./d/ and /edit.Google Sheets, Google Sheets1, Google Sheets2 and Google Sheets3, select it and replace YOUR_SHEET_ID with the ID.Gmail Trigger, Gmail, Gmail1, Gmail2 and Gmail3.Gmail Trigger, add a Search filter so only applications start a run, for example a label you give them.OpenAI.Cal.com Trigger. n8n registers its webhook with Cal.com when you publish.code.Webhook’s production address.The file does not include the script that makes Webhook fire. Webhook expects a POST with the edited cell’s value, its column number and the whole row as a list of lists. This sketch sends exactly that. Put it in the spreadsheet’s Apps Script editor, then add an On edit trigger for it, because a plain onEdit cannot call another server.
function onSheetEdit(e) {
var sheet = e.range.getSheet();
var row = sheet.getRange(e.range.getRow(), 1, 1, sheet.getLastColumn()).getValues();
UrlFetchApp.fetch('YOUR_WEBHOOK_URL', {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ value: e.value, range: { columnStart: e.range.getColumn() }, rowValues: row })
});
}Nothing to press once it is published. A new email adds a row and sends the first email. After that you work in the sheet: tick Screening, Rejected or Test Approved on a row and the matching email goes to the address in column L. Candidates use the forms and the booking page.
| Lane | Starts when | What it writes |
|---|---|---|
| Application | Gmail Trigger finds new mail, checking every hour | A row with the name, address, job, date and code, matched on Indeed Email, then the first email |
| Onboarding | A candidate sends On form submission | Their details by Code, Questions as TRUE, and Rejected as TRUE at one year of experience or less |
| Sheet edits | The Apps Script posts to Webhook | An email: column 7 to Gmail1, column 5 to Gmail2, column 9 to Gmail3 |
| Task | A candidate sends On form submission1 | Test Complete as TRUE and the link in Test Link, by Code |
| Interview | Someone books on Cal.com | Interview Scheduled as TRUE, by the booking’s code answer |
| To change | Where |
|---|---|
| Which mail counts | The Search filter of Gmail Trigger |
| Job-title prompt | The messages in OpenAI, which answers as { "job": "" } |
| Email text | The Subject and Message of the four Gmail nodes. In the edit emails the code in column S is $json.body.rowValues[0][18] |
| Rejection rule | The Rejected expression in Google Sheets1 |
| Form questions | The two form nodes, and the matching columns of Google Sheets1 and Google Sheets2 |
| Which column sends which email | The three rules of Switch, set to 7, 5 and 9 |
Dana Lee writes about a job, with the subject Application: Junior Designer. An hour later OpenAI answers in the shape below, and the sheet has a new row for Dana with Job set to Junior Designer.
{ "job": "Junior Designer" }Dana gets the first email, sends the onboarding form with her code, and the row fills in. When you tick Screening on her row, the sheet’s edit reaches Webhook in this shape, trimmed, and Gmail1 writes to column L.
{
"value": "TRUE",
"range": { "columnStart": 7 },
"rowValues": [["…", "Dana", "Lee", "Junior Designer", "FALSE", "TRUE", "TRUE", "…"]]
}If you are new. n8n draws a workflow as boxes joined by lines, and each box, a node, does one job. Here the canvas shows five rows that share no lines, because the sheet and the code join them, not n8n. A credential is a key n8n stores for you and hands to the node you select it in. Test each lane from its own trigger. The nodes then show what they received and sent.
For experts. Three lanes match rows by Code, and the first matches by the sender’s address.
| Lane | Match column | Notes |
|---|---|---|
| Application | Indeed Email | Append or update, so a second email from the same address updates the row and writes a new random code |
| Onboarding | Code | Appends a new row when no row has that code |
| Task | Code | The same |
| Interview | Code | The booking’s custom code answer |
Filter compares the edited cell’s value with the text TRUE in strict mode, and Switch reads range.columnStart. Webhook answers as soon as it receives the call.
Most risks sit in the open entrances and the blank emails.
Rejected in the sheet but sends nothing. n8n writes through the Sheets API, which does not start your edit trigger, so enter the value yourself to send the emailWebhook takes any POST, so turn on its Authentication and send the same header from the scriptAn n8n workflow. A new applicant email becomes a row in a Google Sheet, and two forms, an edit in the sheet and a Cal.com
booking move each candidate on through screening, a task and an interview.
workflow.json: the workflow as n8n exports it, 16 nodes in five separate lanes, each with its own trigger. It holds nohiring-sheet-edit here.README.md: these notes.Webhook about your edits.Make one spreadsheet and write these 20 column names in row 1, in this order, from column A to column T:
Indeed Email, First Name, Last Name, Job, Rejected, Questions, Screening, Test Complete, Test Approved,
Interview Scheduled, Hire, Email, Resume, Portfolio Link, Years of Experience, Expected Salary, Notes, Date Added,
Code, Test Link
The sheet-edit lane reads columns by position, so keep these where they are.
| Column | Position | Why it matters |
|---|---|---|
| Rejected | E, number 5 | An edit here sends the Gmail2 email |
| Screening | G, number 7 | An edit here sends the Gmail1 email |
| Test Approved | I, number 9 | An edit here sends the Gmail3 email |
| Email | L, number 12 | The address the three edit emails go to |
Indeed Email holds the address the application came from. Code is the key every later step matches on.
workflow.json./d/ and /edit.Google Sheets, Google Sheets1, Google Sheets2 and Google Sheets3,YOUR_SHEET_ID with the ID. Each node finds its tab as the first tab, gid=0.Gmail Trigger, Gmail, Gmail1, Gmail2 and Gmail3.Gmail Trigger, add a Search filter so only applications start a run, for example a label you give them.OpenAI.Cal.com Trigger. n8n registers its webhook with Cal.comcode. Google Sheets3 reads the answer from it.Gmail, Gmail1, Gmail2 and Gmail3. They are empty in the file.Webhook's production address.The file does not include the script that makes Webhook fire. Webhook expects a POST with the edited cell's value,
its column number and the whole row as a list of lists. This sketch sends exactly that. Put it in the spreadsheet's Apps
Script editor, replace YOUR_WEBHOOK_URL, then add an On edit trigger for it under Triggers: a plain onEdit cannot call
another server.
function onSheetEdit(e) {
var sheet = e.range.getSheet();
var row = sheet.getRange(e.range.getRow(), 1, 1, sheet.getLastColumn()).getValues();
UrlFetchApp.fetch('YOUR_WEBHOOK_URL', {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ value: e.value, range: { columnStart: e.range.getColumn() }, rowValues: row })
});
}
Filter lets the call through only when value is the text TRUE, so tick a checkbox or type TRUE. Switch then
sends column 7 to Gmail1, column 5 to Gmail2 and column 9 to Gmail3, and each writes to rowValues[0][11], which is
column L.
| Lane | Starts when | What it does |
|---|---|---|
| Application | Gmail Trigger finds new mail, checking every hour | OpenAI reads the job title from the subject, Google Sheets adds or updates the row matched on Indeed Email, Gmail writes to the sender |
| Onboarding | A candidate sends On form submission | Google Sheets1 updates the row matched on Code, sets Questions to TRUE and sets Rejected |
| Sheet edits | The Apps Script posts to Webhook | Gmail1, Gmail2 or Gmail3 writes to the candidate |
| Task | A candidate sends On form submission1 | Google Sheets2 sets Test Complete to TRUE and saves the link in Test Link |
| Interview | Someone books on Cal.com | Google Sheets3 sets Interview Scheduled to TRUE |
The five lanes share no lines on the canvas. Only the sheet and the code join them.
A new row's Code comes from Math.floor(Math.random() * 999999), a number of up to six digits. First Name and Last Name
come from splitting the sender's display name at the first space. Date Added is written like 02/11/26 09:30AM.
Google Sheets1 sets Rejected to TRUE when Years Of Experience is 1 or less, and to FALSE otherwise.
Gmail Trigger.OpenAI, a gpt-4o-mini call that answers as { "job": "" }.$json.body.rowValues[0] holdsrowValues[0][18], counting from 0.Rejected expression in Google Sheets1.Google Sheets1 and Google Sheets2.Switch, set to 7, 5 and 9.Gmail1 asks for theGmail3 invites the candidate to book, and Gmail2 declines.Google Sheets1 and Google Sheets2 append a new row when no row has that code, so a mistyped codeCode, which breaks the old one.Webhook takes any POST. Turn on its AuthenticationREADME.md 7 KB workflow.json 39 KB
alchaincyf · Skill
Turns a one-line request in your AI agent into a finished design: a launch animation, a clickable app prototype, an editable slide deck, an infographic or a se…
op7418 · Skill
Skill that makes single-file HTML slide decks, slide illustrations and platform covers in two visual styles, with a presenter mode for rehearsal. For speakers…
alirezarezvani · Skill
Adds 411 ready-made skills for Claude Code and other coding agents, grouped by role from engineering and product to marketing, finance and compliance. Installs…
perplexity-ai · Kit
Picks the best option for a decision from text and images, such as which team should handle a request, with a probability for each choice, for developers who b…
numind · Kit
Reads documents as text or images and fills a JSON template with the fields you ask for, or converts the pages to Markdown. A 4B model for teams that process s…
nace-ai · Kit
Scores yes or no, multiple choice and rating questions about a document in one pass, with a probability for every option. An 8B decision model from Nace.AI tha…