HR / marketplace
Career portal
A platform connecting candidates and employers — listings, applications and matching in one place — with search relevance as the hard problem at its centre.
Overview
Candidates and employers on the same market are, on paper, a perfect match — and in practice they rarely find each other efficiently. Listings are noisy, matching is manual, and both sides waste time. This is a career platform that puts listings, applications and matching in one place. It’s in active development, and the interesting problems are exactly the ones you’d expect.
Problem
The naive version of a job portal is a searchable list of postings. That’s the easy 20% and it’s not where the value is. The value is in matching — surfacing the right roles to the right candidates when neither side has the patience to wade through everything. Which makes search relevance, not CRUD, the core engineering problem.
Solution
A platform where employers post roles, candidates apply, and the system does real work to connect the two rather than just storing both. A Symfony backend owns the domain; a Vue.js frontend serves both sides of the marketplace; OpenSearch powers discovery and relevance; MySQL holds the canonical data; and the whole thing runs in Docker.
Because it’s in active development, this write-up is honest about being a snapshot rather than a finished postmortem — the architecture below is the shape it’s taking, and some of it is still being proven out.
Architecture
The design treats search as a first-class subsystem from day one, not something to add once the CRUD is done. OpenSearch is the discovery layer, kept in sync with the MySQL system of record so results never lag reality. Symfony gives the domain a disciplined structure — entities, clear boundaries, room to grow — and the Vue frontend consumes it as an API rather than reaching into it.
Keeping the marketplace’s two audiences (candidates, employers) coherent in one product means being deliberate about where their flows share machinery and where they diverge, so a change on one side doesn’t quietly break the other.
Technical challenges
Relevance is the recurring one — matching candidates and roles well enough that both sides trust the results, which is a tuning-and-iteration problem more than a build-it-once one. And as a live project, a real challenge is the ordinary discipline of building something non-trivial incrementally: keeping each step shippable, keeping the search index honest as the schema evolves, and resisting the urge to over-build the matching before there’s usage to learn from.
Lessons learned
Still being written — which is the honest answer for a project in flight. The early lesson is the same one the marketplace projects keep teaching: identify the one thing the product is actually for (here, matching) and refuse to let it become an afterthought behind the easy scaffolding. I’ll update this as it ships.