A career platform built for a skills mismatch, with a seeker side and an employer side. Sample records throughout.
Job timeline
A feed rather than a search box, because the match score is computed per user before they ask.
- Sample role A84% match · median salary tag
Confidence is specific to this seeker, not a popularity score.
- Sample role B71% match · median salary tag
- Sample role C63% match · median salary tag
Median salary sits on every card on purpose: the platform exists for a market where underpayment is the normal outcome of not knowing the number. Built mobile-first and light enough for low-end phones and thin data.
From a profile to a confidence score
Four sections embedded separately, then recombined — a strong skills match should not be hidden by a thin education section.
Section weights
The matching pass
- 1embed profile per section
- 2query postings per section
- 3calibrate similarity
- 4weighted aggregate
- 5cross-encoder rerank
- 6LLM judge on the top results
- 7blend and return
Raw cosine similarity is too generous — almost everything looks like a 70% match. Scores are pushed through a steep logistic curve first, so a mid-range similarity reads as the weak match it is. An 84% has to be earned.
Three passes, narrowing
- Vector retrievalper section, top 30
Cheap, wide, run for every section of the profile.
- Cross-encoder reranktop 50
More expensive and more accurate; blended with the vector score rather than replacing it.
- LLM judgetop 15
Scores each section in context, then is blended per section — and when the judge and the vectors agree, the judge is trusted more.
Role to roadmap
The idea the project is built around: a match score on its own tells you nothing you can act on.
From a role to a plan
- 1Pick a target role
- 2Locate the current milestone
- 3Score the gap
- 4Learning step
- 5Portfolio piece
- 6Apply
Sample milestone scores
What a milestone carries
- Matched evidencefrom the profile
The specific items that justify the score, each with where it came from.
- Gapswhat is missing
Named explicitly, because this is the part that becomes the next step.
- Rationalewritten
Why the score is what it is.
- ETAhours · confidence
With a confidence attached, and a low-confidence flag when the profile is too thin to estimate honestly.
- Resources and certificationslinked
Suggested per milestone rather than per role.
The roadmap recomputes when the profile changes, so completing a milestone moves the seeker rather than leaving a stale plan on screen.
Resume builder
Sample profile
generate (demo)The four fields are the four sections the matcher embeds. Filling the profile in is the same act as improving the match, which is the only reason a seeker keeps it current.
Application
Application status
Withdrawn and rejected are terminal branches off this line, not stages in it.
- 1draft
- 2submitted
- 3shortlisted
- 4interviewed
- 5offered
- 6hired
data model job_applications
job_post_id / job_seeker_id / employer_idrefmatch_confidencenumericthe score at the moment of applyingmatch_snapshotjsonthe section scores behind it, frozen — so a later model change cannot rewrite historystatus / status_changed_attext · timestampdraft · submitted · shortlisted · interviewed · offered · rejected · hired · withdrawnsource / resume_urltextApplying twice to the same posting updates the existing application rather than creating a second one. Row-level security scopes every query to the signed-in seeker.
Candidates
| Candidate | Match | Stage | Applied |
|---|---|---|---|
| Candidate 01 | 90% | shortlisted | sample date |
| Candidate 02 | 84% | submitted | sample date |
| Candidate 03 | 71% | interviewed | sample date |
| Candidate 04 | 66% | submitted | sample date |
The employer sees the same confidence the seeker saw, computed the same way. One score, two audiences — otherwise neither side trusts it.
Posting a role
data model job_posts
job_title / job_company / job_locationtextjob_overviewtextjob_skillstext[]the section the matcher weights highestjob_experiencejson[]years in a named area, parsed rather than free textjob_education / job_licenses_certificationstext[]salaryjsonwhich is what the median salary tag is drawn fromjob_type / deadline / statustext · date · textpinecone_id / embedding_checksumtextthe checksum is what stops a posting being re-embedded when nothing meaningful changedBuilt by a five-person team. Third place and Most Promising Prototype at AI.DEAS 2025.