Job Match Pipeline
Job postings are spread across several sources, the same posting often appears more than once, and judging how well each one fits takes time. This pipeline gathers postings every day, merges them into one clean list, and ranks them against my CV, so the best matches come first with a written fit/gap analysis.




How it works
- 1Ingest
A scheduled job pulls new postings daily from multiple job APIs.
- 2Normalize & dedupe
Every source is mapped into one data model, and duplicates across sources are removed.
- 3Filter & score
Hard filters drop non-matches, then weighted subscores rank the rest.
- 4Semantic match
Text embeddings (Voyage AI) measure CV-to-job similarity as one of the subscores.
- 5LLM analysis
An LLM via OpenRouter writes a fit/gap analysis for the top matches.
- 6Dashboard
A Nuxt 4 dashboard shows the ranked jobs with filters, an application tracker, CV upload and stats charts.
- Ranked job table with filters for source, location, work mode, application status and seniority
- Job detail panel with the fit/gap analysis, application status, date and notes, and a per-category score breakdown
- Stats on the skills postings ask for (mine vs. others), salary distribution by source with currencies converted at ECB rates, and postings over time
- CV upload that recognizes skills and stores only the extracted text, plus matching preferences such as required skills, minimum salary and acceptable locations
- PostgreSQL on Neon (serverless Postgres), accessed through Prisma ORM
- Scheduled pipeline job running on Railway
- Dashboard deployed on Vercel
- Vitest unit tests for the parsers, scoring and deduplication
- Playwright end-to-end browser tests for the dashboard
- Both suites run in GitHub Actions CI