Recruiting
Candidate pipeline for a recruiting agency
A recruiting agency tracks candidates through stages for each open role, records who introduced whom and when, and shows the client a shortlist without revealing the rest of the pipeline. Fees are calculated when a candidate is placed.
Automatically generated draft
Written by machine against our own engineering playbook. The company is invented; the decisions are the ones we would make on a real build. A reviewed blueprint goes further — nine sections, agreed line by line, and it is what the build is tested against.
Section 01 · What has to work
The system must provide a confidential pipeline for the agency while exposing only the approved candidate shortlist to each client.
Section 03 · Screens
Every screen, and what it is for.
- ›Pipeline View — Recruiter manages candidates for a role; moving a candidate must be instant.
- ›Candidate Profile — Recruiter views full history and notes; adding a note must be instant.
- ›Client Shortlist — Client views approved candidates for their role; loading a profile must be instant.
- ›Placements Ledger — Agency admin tracks placed roles; calculating total fees must be instant.
Anything not on this list is not in version one. That is what keeps a fixed price fixed.
Section 04 · The data model
What it stores, and who can read a row.
Organization
id uuid, name text, type enum('agency', 'client')
Access · Agency staff can read all; clients can only read their own row.
User
id uuid, organization_id uuid, email text, role enum('recruiter', 'client', 'admin')
Access · A user can read their own row; admins can read all users.
Role
id uuid, client_organization_id uuid, title text, description text, fee_percent numeric(5,2)
Access · Recruiters read all roles; clients read roles for their organization.
Candidate
id uuid, name text, contact_details_encrypted text, introduced_by_user_id uuid, introduced_at timestamptz
Access · Agency staff can read all candidates; clients cannot read this table.
Application
id uuid, candidate_id uuid, role_id uuid, status enum('sourced', 'screening', 'shortlisted', 'interviewing', 'offer', 'placed', 'rejected'), notes_internal text
Access · Agency reads all; client reads only if status is 'shortlisted' or later.
Those access rules belong in the database, not in the screens. Someone who edits the address bar still cannot read a row that is not theirs — and the test that proves it blocks delivery if it fails.
Section 05 · States
Sourced → Screening → Shortlisted → Client Interview → Offer → Placed | Rejected
Most scope arguments three weeks into a build are really arguments about a state nobody named at the start.
Section 06 · Where this breaks
What bites products like this one.
A client sees a candidate not on their shortlist, breaking confidentiality.
Every database query must filter applications by both client organization and status.
Two recruiters update the same candidate's application status simultaneously, causing a data race.
Use optimistic locking on the Application table to detect and handle concurrent edits.
An introduction is recorded incorrectly, leading to commission disputes.
The `introduced_by_user_id` and `introduced_at` fields must be immutable after initial creation.
Section 08 · Deliberately left out
What version one does not do.
- ×Complex, multi-part fee calculations. V1 will use a single percentage fee per role.
- ×Full historical audit log of every change. V1 tracks current state and key timestamps only.
This is the section that protects the date, and the only place in the document where somebody says no. It is also why clients trust the rest of it.
Still open
What we would ask before quoting.
- How is a placement fee defined? Is it a single percentage of salary, a flat fee, or something more complex?
- Can a single candidate be submitted to multiple roles for different clients simultaneously?
- Who can add a new candidate to the system, and where do they come from (e.g., manual entry, LinkedIn import)?
Your product, not this one
Get this written for what you are actually building.
Describe it in a sentence and the generator returns the same sections for your own product. Free, no email, nothing saved to a list.
Next step
Find out if your idea fits in 10 working days.
Tell us what you want to build. We reply the same day with a straight yes, no, or here is what we would cut.