Why
The career-ops workflow I use day-to-day runs on a separate system, but I wanted a clean full-stack version that could onboard someone from zero: paste a resume, paste a LinkedIn URL, get a usable skill graph and a gap analysis.
What it does
- Resume parsing: PyMuPDF pulls the text, an LLM normalizes it into a structured skill + experience schema.
- LinkedIn scraping: via a Cloudflare API layer to handle the brittleness.
- GitHub analysis: pulls repo metadata, README summaries, and language breakdowns.
- Skill normalization: LLM collapses "FastAPI / FastApi / fastapi" and similar variants to a canonical vocabulary.
- Verification quizzes: generated per skill so claims can be checked.
- Gap analysis: compares against a target role and surfaces what's missing.
- Job match scoring: scrapes LinkedIn job postings and ranks them against the normalized profile.
Interesting bits
The skill-normalization step matters more than any single scraper. Resumes, LinkedIn, and GitHub all name the same thing differently; without canonicalization the match scores are noise. I kept the canonical vocabulary in a simple SQLite table with alias rows, so the normalizer can be audited and corrected without retraining anything.
Stack
FastAPI · Next.js · SQLite · PyMuPDF · OpenAI API · Cloudflare API · TypeScript