From a tutoring marketplace to an explainable matching benchmark
The insight worth keeping was never the payments stack — it was how the ranking is built and explained.
benchmarks/edumatch.What was ported, what wasn't
| Stage | Stack | Core idea | Where it hit a wall |
|---|---|---|---|
| Personal project | Next.js · Prisma/Postgres · Stripe Connect · geocoding | A full tutoring marketplace: intake, tutor discovery, quotes, Stripe-split payments, disputes, verification, notifications. | The matching algorithm itself — the actual product insight — was buried inside a large, credentialed, stateful app that can't be shown publicly as-is. |
| This benchmark | Pure JS engine · synthetic fixtures · client-side demo | Extract just the matching logic, make it explainable and adjustable, and prove it with deterministic tests instead of a live marketplace. | Deliberately no accounts, payments, geocoding, or verification — the Journey page simulates the workflow shape without any of the real infrastructure. |
How the benchmark is built
Hard requirements (subject, level, language, availability, mode/distance) are checked before any scoring happens. A tutor who fails one is never ranked — and the reason is recorded, not discarded.
Every ranked result carries a factor-by-factor breakdown (value × weight = contribution) that sums exactly to its composite score — there is no hidden step between 'why' and 'what.'
The engine is a single ESM module imported by the Node test suite, the fixture generator, and the Showcase's client-side Match Explorer — there is no second implementation to drift out of sync.
The legacy algorithm normalised rating as avg / 5, which let a single five-star review outrank a tutor with forty consistently strong ones. This version damps toward a neutral prior so review count matters.
What we gave up, and why
The public surface cannot create a real booking or move real money. That rules out 'try it against real tutors' demos, but it's the only honest way to publish a matching demo without a moderated, credentialed backend.
Twelve tutors and six needs are enough to demonstrate the method precisely — a deliberate twin pair, a tight-availability case, a no-qualified-tutor case — but they are not a statistically representative population.
Lessons from the legacy system
The legacy scorer produced a single number. Retrofitting an explanation after the fact is much harder than building the factor breakdown as the primary output from day one, which is what this version does.
Saying "the algorithm doesn't use protected attributes" is a claim. A constraint-identical twin pair that must score identically is a test. See the Fairness page.
- Real provider adapters (an LLM for scripts, a render worker for video) implementing the same ScriptProvider/RenderProvider interface, gated behind explicit flags and a cost confirmation step.
- Real asset storage, licensing, and rights verification for any non-synthetic media.
- Durable queue/worker infrastructure so a job survives a process restart, with the same state machine and idempotent-retry semantics enforced server-side.
- Audit logging and access control around who can approve or reject a run at each gate.