Case study, personal tool

Career Copilot

A personal tool for my internship search. It collects openings from 22 sources, ranks them against my profile and tracks my applications. It runs locally, on my laptop.

Role
Personal project
Stack
Python, Playwright, FastAPI, SQLite
Runs on
Locally, on macOS
Interfaces
Desktop app and web dashboard
Career Copilot, demo
The web dashboard on demo data: companies, openings and people are made up.
22connected sources: 4 portals, 9 ATS and 9 job boards
250automated tests
16,386lines of code
The problem

Too many sources, the same openings.

Internships are scattered across job portals, applicant tracking systems and company careers pages. Checking them by hand every day was slow, and the same role showed up several times on different sources.

Portals

Automated browser or feeds

  • LinkedIn
  • Indeed
  • Glassdoor
  • Welcome to the Jungle

ATS

Companies' public APIs

  • Greenhouse
  • Lever
  • Ashby
  • Workable
  • SmartRecruiters
  • Teamtailor
  • Recruitee
  • Personio
  • Workday

Job board

APIs and RSS feeds

  • Himalayas
  • RemoteOK
  • AI Jobs
  • NoDesk
  • Music Business
  • Work With Indies
  • TopStartups
  • JobFluent
  • theInterna
What I built

Find, score, track.

Network Radar: summary and openings to act on, each with its score

Find

Searches portals, ATS boards and careers pages from one interface and keeps everything in a local archive, without duplicates.

Network Radar, demo data
Opening detail with Match 94, CV Match 95% and AI Fit Strong

Score

Each opening gets a relevance score, a CV match score and an AI verdict with its reasoning.

Opening detail, demo data
Applications Kanban: applied, interview, offer, closed

Track

A Kanban keeps status, dates and follow-ups for every application; Network Radar links companies to people worth contacting.

Applications Kanban, demo data
How a score is made

Perfect Fit, line by line.

Each opening adds up relevance, CV match and the AI verdict with fixed weights, plus two bonuses. If the AI judges it off-profile it loses 55 points: a well-written title is not enough.

Founder's Associate Intern

Velarion, Berlin. Target company, AI verdict: maybe

86
  • +31.7Relevance 69 × 0.46
  • +28.9CV Match 76 × 0.38
  • +7.6AI 63 × 0.12 (maybe)
  • +18Target company 10, internship 8

Business Development Intern

Mirelune, Stockholm. Target company, AI verdict: not a fit

9
  • +26.7Relevance 58 × 0.46
  • +19CV Match 50 × 0.38
  • +18Target company 10, internship 8
  • −55AI verdict: not a fit
Precision

Fewer openings, the right ones.

Reviewing the filters I found two mistakes: some titles counted as internships because one word contained another, and the same opening was saved once per source. Terms are now matched as whole words, and duplicates are recognised by title, company and city.

TitleBeforeNow
International Sales ExecutiveInternshipExcluded
Internal Audit SpecialistInternshipExcluded
Backstage Operations SpecialistInternshipExcluded
Marketing InternInternshipInternship
LinkedInGrowth Marketing Intern (m/f/d)
Velarion GmbH, Berlin
Company ATSGrowth Marketing Intern
Velarion, Berlin, Germany
ArchiveOne opening
The second source is skipped before the AI analysis.
How it works

From sources to pipeline.

  1. SourcesPortals, ATS boards and job boards.
  2. CollectionA time limit per source: if one is blocked, the others carry on.
  3. FiltersWhole words, chosen cities, one row per opening.
  4. ScoresRelevance, CV match and AI verdict.
  5. ArchiveLocal SQLite, desktop app and web dashboard.
Technical choices

Six concrete decisions.

  • Public ATS APIs where they exist: Greenhouse, Lever, Ashby, Workable and SmartRecruiters. The automated browser is used only for sources without one.
  • Consistent browser-like requests. One reused session per source and retries only on 429 and server errors: a 403 or 404 does not improve by retrying.
  • Bounded run times. 10 minutes for API sources, 45 for browser sources. When time runs out, the openings already read are kept.
  • Updates without losing anything. When an opening is read again, status, notes and follow-ups stay as they were.
  • Nothing is sent without my approval. The app prepares drafts and materials; I send applications and messages myself.
  • 250 automated tests on temporary databases, so real data is never touched.
What I'd do next

Keep only the sources that work.

I'd measure which sources actually lead to interviews and use that to weight the ranking.