All projects
Full stackOngoing

Job Match Pipeline

Pulls job postings daily from several APIs, removes duplicates, and ranks them against my CV using embeddings and LLM fit/gap analysis.
Overview

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.

Ranked jobs with filters and application status
Ranked jobs with filters and application status
Job detail: LLM fit/gap analysis, application tracking and score breakdown
Job detail: LLM fit/gap analysis, application tracking and score breakdown
Stats: skills in demand, salary distribution and postings over time
Stats: skills in demand, salary distribution and postings over time
Profile: CV upload with skill recognition and matching preferences
Profile: CV upload with skill recognition and matching preferences

How it works

  1. 1Ingest

    A scheduled job pulls new postings daily from multiple job APIs.

  2. 2Normalize & dedupe

    Every source is mapped into one data model, and duplicates across sources are removed.

  3. 3Filter & score

    Hard filters drop non-matches, then weighted subscores rank the rest.

  4. 4Semantic match

    Text embeddings (Voyage AI) measure CV-to-job similarity as one of the subscores.

  5. 5LLM analysis

    An LLM via OpenRouter writes a fit/gap analysis for the top matches.

  6. 6Dashboard

    A Nuxt 4 dashboard shows the ranked jobs with filters, an application tracker, CV upload and stats charts.

Dashboard
  • 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
Data & infrastructure
  • PostgreSQL on Neon (serverless Postgres), accessed through Prisma ORM
  • Scheduled pipeline job running on Railway
  • Dashboard deployed on Vercel
Testing & CI
  • 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
Stack
TypeScriptNode.jsNuxt 4PostgreSQLPrismaNeonVoyage AIOpenRouterVitestPlaywrightGitHub ActionsRailwayVercel

© 2026 Daniel Paulino • Built with Nuxt • Updated October 2026