Personal project · Browser-local AI / 2026
FitCheck
A private, evidence-backed way to read a role.
A browser-local job-description analyzer that compares role requirements with public resume evidence, then surfaces approximate fit, gaps, and questions to verify.
01Job description input
A recruiter pastes a job description into the analyzer. Input is limited to 200–20,000 characters and remains in page memory for the active session.
02Needle 3.2 WASM runtime
Needle is a compact on-device tool-calling runtime. Its pinned browser JavaScript, WASM engine, and model archive load lazily inside a Web Worker so the main UI remains responsive.
03Structured requirements
Needle extracts role title, seniority, experience, required skills, preferred skills, responsibilities, and education or certification requirements. Incomplete model fields are supplemented by deterministic local extraction.
04Resume evidence and embeddings
FitCheck builds evidence only from public professional fields: skills, experience, projects, education, and certifications. Needle creates in-memory embeddings for extracted requirements and resume evidence.
05Weighted fit scoring
Exact normalized aliases receive full matches. Otherwise cosine similarity classifies evidence as match, partial, or gap. Available categories are weighted and missing categories are redistributed without inventing evidence.
06Optional AI explanation
After an explicit click, a compact set of derived role and match facts can be sent to the explanation endpoint. The original JD stays local and is never included in that request.
Problem & context
Recruiters often need a quick first read of whether a candidate’s public work relates to a role, but a generic keyword search misses evidence spread across projects, experience, and technical skills. FitCheck turns that first read into an inspectable portfolio signal while keeping the pasted job description inside the recruiter’s browser.
What Needle contributes
Needle is a compact local runtime for structured tool calling and embeddings. FitCheck uses the pinned Needle 3.2 browser assets to extract job requirements and create vector representations without Pinecone or a remote embedding call. The runtime and model archive are loaded only when the analyzer opens and run inside a Web Worker.
Browser-local pipeline
The page sends the pasted JD and resume evidence to a dedicated worker. The worker initializes Needle, extracts a normalized job profile, creates embeddings for requirements and evidence, and returns only structured results to the UI. The main thread performs deterministic comparison and renders matched requirements, partial matches, gaps, and recruiter prompts.
Evidence and scoring model
The weighted score uses required skills at 45%, preferred skills at 10%, responsibilities at 25%, experience and seniority at 15%, and education or certifications at 5%. Exact normalized skill or alias matches receive full credit. Embedding similarity of at least 0.78 is a match, 0.62–0.779 is partial, and below 0.62 is a gap. Missing categories have their weight redistributed proportionally; fewer than two scorable categories returns a not-enough-detail state. The result is an approximate portfolio fit signal, not an ATS result or hiring recommendation.
Privacy and optional explanation
Core analysis uses no Pinecone, Redis, database, localStorage, sessionStorage, IndexedDB, cookies, or backend request. JD text, embeddings, and results stay in memory and are cleared on refresh, navigation, page exit, or the Clear action. The optional explanation runs only after an explicit recruiter click and receives compact derived facts rather than the original JD.
Failure handling and fallback extraction
Local model output can contain incomplete structured tool calls, so the worker accepts supported Needle response shapes, validates fields, and supplements missing role, experience, skill, responsibility, and education data with deterministic extraction from recognizable JD sections. Low-confidence results remain visible but are labelled directional. A model-load or analysis failure leaves a clear error state instead of producing a fabricated score.
Validation and limitations
Unit tests cover normalization, aliases, cosine thresholds, weighted scoring, weight redistribution, and insufficient-detail handling. TypeScript, lint, and production builds validate the frontend integration. The implementation does not claim production recruiter usage, benchmark accuracy, or universal document parsing; V1 accepts pasted text and treats location and personal attributes as outside the score.
Engineering decision records
01 / Keep JD analysis local
Context. A recruiter may paste confidential role information that should not become portfolio memory or enter the existing retrieval system.
Decision. Run extraction, embeddings, comparison, and scoring in the browser without Pinecone, Redis, persistence, or a core backend request.
Trade-off. Privacy and teardown behavior are clear, while model download size and browser capability become visible constraints.
02 / Run Needle inside a worker
Context. WASM model initialization and local embedding work can block the interface if performed on the main thread.
Decision. Load pinned Needle browser assets lazily in a dedicated Web Worker and reset its model state between unrelated analyses.
Trade-off. The UI stays responsive and the model remains local, at the cost of worker lifecycle and unsupported-WASM handling.
03 / Recover from incomplete extraction
Context. A compact local model may return suppressed or partial structured calls for long, formatted job descriptions.
Decision. Validate Needle output and use deterministic section and keyword extraction to fill missing fields before scoring.
Trade-off. Valid JDs produce useful directional results more consistently, while fallback confidence and limitations must remain visible.
04 / Make cloud explanation opt-in
Context. A polished explanation can help a recruiter, but automatic cloud transmission would conflict with the local-first promise.
Decision. Require an explicit Generate AI explanation action and send only normalized role, match, gap, and resume-evidence facts.
Trade-off. The local score remains usable without a provider, while explanation availability depends on backend and OpenRouter configuration.