Art The VA Specialist
Back to Web Apps

Private internal tool for a US home care staffing company

Recruitment Talent Pool

An internal hiring tool that turns every résumé a home care agency has ever received into a searchable, scored talent pool.

The Talent Pool interface after a pasted job description set its requirement filters and ranked the shortlist by fit.
Shown on a synthetic demo build generated from the same template as the production app. A pasted job description has set five requirement filters, and the shortlist is ranked by fit. Every person shown is invented.

The problem

Recruiters had a folder of PDF résumés and a spreadsheet. Finding “someone who can own a scheduling calendar and has real clinical exposure” meant opening files one at a time, and every new job posting started that search from zero. What anyone knew about a candidate lived in whoever happened to remember it.

The search that returned the wrong 634 people

The first version matched a pasted job description by keywords. A posting for an outbound sales role described someone who would speak with “business owners, executives, HR and finance decision makers”. The word HR appeared, so the tool set a minimum HR competency and cut the shortlist to 634 people.

But HR was who the candidate would be calling, not a skill the candidate needed. Every one of those 634 results had been filtered on a misreading, and nothing about the result showed it. It simply looked like a confident answer.

The fix was to stop matching words and start reading the posting as a specification: what does an applicant actually have to be able to do already. Read that way, the same posting returned 1,213 people, nearly twice as many, and the right ones.

Ranking by keywords is fine. Gating by keywords is not. A wrong ranking term moves someone a few places down a list. A wrong gate removes hundreds of people silently, and nobody ever finds out.

That distinction now runs through the whole tool. A pasted description decides two separate things through two separate mechanisms: what is required, which controls who appears at all, and what the wording merely suggests, which only controls the order.

Same job description, two ways of reading it

Gated by keywords

634

Cut down because the word “HR” appeared in the posting. HR was who the candidate would phone, not a skill they needed. Hundreds of the right people were removed silently.

Read as requirements

1,213

Filtered on what an applicant must already be able to do. Nearly twice as many people, and the right ones.

How it holds up

Reading a job description as a specification

The posting goes to a language model that returns a minimum required score per competency, plus a plain sentence explaining what it concluded. Every answer is validated before it is trusted: scores are clamped to the valid range, competencies it invents are dropped, and a reply that tries to require all eight at once is rejected outright, because a shortlist gated on everything returns nobody. If the model is slow or unreachable, the tool falls back to its own local matching and says so in one quiet line, so the search button always returns something.

It says what it cannot do

The rubric scores eight competencies, and sales is not one of them. When a posting needs cold calling, the tool sets the filters it can defend, then states plainly that it cannot filter for the sales experience the role needs. Surfacing that gap is what makes the rest of the answer trustworthy.

Security you do not usually see in an internal tool

It holds names, phone numbers and email addresses for around 2,800 real applicants, so it is built like it. The page sits behind a token gate, embedding is limited to specific parent domains, applicant data is never cached, and the CSV export neutralises spreadsheet formula injection, because a cell that begins with an equals sign runs as a formula in Excel and that text comes from applicant résumés.

Fast, with no framework

The whole application is one self-contained HTML file, with no React and no build step. Ranking 2,880 candidates against a pasted posting takes about 120 milliseconds, because the search index is built quietly after the page loads and each candidate is scanned once rather than once per search term.

What it deliberately is not

  • Intake is still manual. Résumés are processed in batches on request, not continuously. A design to automate that exists and is not built yet.
  • The page loads every record at once. That is fine at the current size and will need rethinking as the pool grows.
  • It does not make hiring decisions. It scores demonstrated competencies and lets a recruiter filter on them, and roles that need something outside the eight competencies are surfaced to the recruiter rather than guessed at.

Stack

Vanilla JavaScriptPython data pipelineCloudflare Workers + KVLLM job-description parsingWorkflow automationSecurity-hardened

Vanilla JavaScript, a Python data pipeline, Cloudflare Workers and KV, and workflow automation for email and language-model calls, embedded as a widget inside the client’s existing dashboard.

This is a private internal tool, so there is no public link and no live demo. Every screen shown here is generated from synthetic data. Details available on request.

Want a system like this running your agency?

Book a 30-minute call. Bring your messiest process, and I'll tell you exactly how I'd automate it.

Book a call