Open source · Solo project
An open-source hiring marketplace where the ranking is the product: jobs surface the right candidates, candidates surface the right jobs, and both sides are scored by the same rules. Built as a reference for search that gets measured instead of guessed at.
The pipeline is the pattern search engines and recommenders use: retrieve a wide set fast, then spend the expensive scoring on that set only. Qdrant returns the top 50 by approximate nearest neighbor, and a multi-factor model re-ranks those to the top 10.
Retrieval runs under the hard constraints first. Work mode, location and relocation are payload filters Qdrant applies before the nearest-neighbor step. Vectors are 3072-dimensional Gemini embeddings, indexed with HNSW and compared by cosine distance, so search stays sub-linear as the candidate pool grows. HNSW exposes m and ef_construct at index time, which is where the precision and recall tradeoff actually gets set.
Re-ranking combines four signals: semantic similarity carried over from retrieval, keyword recall between extracted skills and stated requirements, experience fit on years and seniority, and soft constraints such as salary range and start date. One function scores job→talent and talent→job. Both sides of the marketplace are ranked by the same rules, so the two directions cannot drift apart.
The weights are a deliberate starting point, not a tuned result. NDCG@10 is the primary ranking-quality metric, and the eval framework is built to tune against it as soon as recruiter-labeled ground truth exists. The eval groups cover each layer:
The framework follows Anthropic's methodology of tasks, trials and graders, with a strict split: dev sets (60%) for iteration, held-out test sets (40%) for the final comparison. Deterministic code graders cover objective accuracy, LLM rubric graders cover the subjective part.
An LLM turns a resume into skills, experience, preferences and constraints, and a job description into requirements, responsibilities and qualifications. Where something is missing it asks a follow-up question instead of guessing. Every processed record is embedded and indexed automatically.
Effect.ts carries this beyond convention. Services are Context.Tag, so the type system rejects a program until every dependency is provided: missing wiring is a compile error, not a 3am runtime one. Every failure mode is a discriminated union rather than a thrown exception, which means the compiler lists the cases you have not handled. @effect/rpc carries the same schemas across the frontend and backend boundary, validated on both sides.
Turborepo and Bun, split so each package has one job:
Gemini 2.0 Flash does the structured extraction and the clarifying questions. Gemini embeddings produce the 3072-dimensional vectors. TypeScript runs in strict mode across every package, with Ultracite over Biome for linting.
30K+leads generated
An event marketing platform for B2B sales teams. It finds the right people before a trade show and talks them into coming, then captures everyone who stops at the booth and follows them up while the event is still running.
15Kmonthly active users
A marketplace that puts artists' work on hotel walls and lets guests buy the piece they are looking at: hosts get free curation, artists get a sales channel, guests take the art home.
A catalogue of B2B software where buyers ask a question in plain English and get an answer back from the live listings, instead of clicking through category pages.
If retrieval, ranking or matching sits at the center of your product, I can build the pipeline and the evals that tell you it actually works, on architecture that lets you swap the pieces later.
Book a free call30 minutes, free. You leave with a plan either way.