Skip to content
kdbrianPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Seevy

See your CV across its historical timeline. Upload every version of your CV as it changes over the years. Seevy keeps them all and shows you how it drifted — for better or worse.

  • Timeline — CV‑health score and key writing metrics per version, plus a graded, sortable table, so you can tell whether each rewrite actually helped.
  • Diff — exactly what text changed between any two versions (word or line level).
  • Misfits over time — where the CV regressed: quantified achievements you dropped and never brought back, bullets that got weaker, skills that vanished, buzzwords creeping in, timeline gaps, ATS regressions.
  • ATS readiness (Sept 2026) — a 12‑point applicant‑tracking‑system audit per version with an ordered fix list; the score also rides the timeline chart.
  • Final boss — every unique bullet you've ever written, clustered and ranked. Bulk‑select the keepers and export a Markdown draft toward one definitive CV.
  • Automatic dating — Seevy reads the dates inside each CV and places it on the timeline itself; you can still override.
  • Expert review (optional) — with an Anthropic API key, each version can get a written critique from a simulated staff‑engineer + recruiter + career‑coach panel.

The analysis engine is deterministic and runs offline. The only thing that needs a network or a key is the optional AI review.


Two ways to run it

Static build (GitHub Pages) Full build (local / Docker)
Runs 100% in the browser Node server + SQLite
Storage localStorage (this browser only) data/seevy.db + data/uploads/
PDF / DOCX parsing in‑browser (pdf.js / mammoth via CDN) pdf-parse / mammoth on the server
AI expert review ✗ ✓ (with ANTHROPIC_API_KEY)
Original file download ✗ ✓
Backup / restore ✓ (JSON export/import) ✓
Deploy git push → GitHub Actions → Pages npm start or docker compose up

Both share the exact same analysis engine (src/analyze.js, src/misfits.js, src/diff.js, src/curator.js); the static build bundles it with a localStorage backend via esbuild.


Quick start (local, full build)

Requires Node 22.5+ (Seevy uses the built‑in node:sqlite).

git clone git@github.com:kdbrian/Seevy.git
cd Seevy
npm install
npm start
# open http://localhost:4173

Upload a couple of CV versions and every view lights up. Data persists in ./data.

Docker

docker compose up --build
# open http://localhost:4173

./data is mounted into the container, so your history survives rebuilds.

Optional: AI expert review

cp .env.example .env
# then edit .env:
#   ANTHROPIC_API_KEY=sk-ant-...
#   SEEVY_MODEL=claude-sonnet-5   # optional, default claude-opus-5
npm start

A Run expert review button then appears on each version. Reviews are saved with the version. Without a key, everything else is unchanged.


Deploy to GitHub Pages

The repo ships .github/workflows/deploy.yml. It builds the static site and publishes it on every push to main.

One‑time setup: on GitHub → Settings → Pages → Build and deployment → Source: GitHub Actions.

Then:

git push origin main

The workflow runs npm ci → npm run build:web (esbuild → dist/) → upload-pages-artifact → deploy-pages, and your site goes live at:

https://kdbrian.github.io/Seevy/

Build it locally to preview the exact artifact:

npm run build:web
npx serve dist        # or any static server

Configuration

Variable Default Purpose
PORT 4173 HTTP port (server build)
HOST 0.0.0.0 Bind address (server build)
SEEVY_DATA_DIR ./data Where the SQLite db and uploads live
ANTHROPIC_API_KEY — Enables AI expert review
ANTHROPIC_AUTH_TOKEN — Alternative to the API key
SEEVY_MODEL claude-opus-5 Model used for reviews

server.js loads a .env file itself — no dotenv dependency.


How the core engine works

Every version, in both builds, goes through the same pipeline. The storage layer is the only part that differs.

flowchart TD
    A["Upload file or paste text"] --> B{"File type?"}
    B -->|pdf| C1["Extract text<br/>pdf-parse (server) / pdf.js (browser)"]
    B -->|docx| C2["Extract text<br/>mammoth"]
    B -->|txt / md| C3["Read as text"]
    C1 --> N["normalize()<br/>src/normalize.js"]
    C2 --> N
    C3 --> N

    N --> AN["analyze(rawText, ctx)<br/>src/analyze.js"]
    AN --> M1["Heuristic metrics<br/>quantified %, action verbs,<br/>buzzwords, passive, sections, skills"]
    AN --> M2["CV-health score 0–100<br/>+ per-factor breakdown"]
    AN --> M3["ATS audit — 12 checks<br/>+ ordered fix list (Sept 2026)"]
    AN --> M4["inferDate()<br/>most recent date in the CV"]

    M1 --> ST[("Store<br/>SQLite  ||  localStorage")]
    M2 --> ST
    M3 --> ST
    M4 --> ST

    ST --> V1["Timeline<br/>graded, sortable"]
    ST --> V2["Diff<br/>src/diff.js"]
    ST --> V3["Misfits<br/>src/misfits.js — cross-version"]
    ST --> V4["Final boss<br/>src/curator.js — cluster + rank"]

    V4 --> EX["Export Markdown draft"]
    ST --> BK["Backup / restore JSON"]
    ST -.->|"API key set,<br/>server build only"| AI["Claude expert review<br/>src/ai.js"]
Loading

analyze() is pure and dependency‑light on purpose: the browser build imports the same file.

One upload, end to end (static build)

sequenceDiagram
    participant U as User
    participant App as app.js
    participant BE as backend.js<br/>(localStorage adapter)
    participant Eng as Engine<br/>(bundled src/*)
    participant LS as localStorage

    U->>App: drop CV / paste text
    App->>BE: createVersion({file|text, label, dated_at})
    BE->>Eng: extractText() then analyze()
    Eng-->>BE: metrics + score + ATS + inferredDate
    BE->>LS: persist version record
    BE-->>App: public version object
    App->>BE: timeline() / misfits() / curator()
    BE->>Eng: detectMisfits() / buildCuration() over all versions
    Eng-->>BE: assembled view data
    BE-->>App: render Timeline / Misfits / Final boss
Loading

Commit & sync (deploy pipeline)

flowchart LR
    subgraph Local["Your machine"]
        D["Edit code"] --> C["git commit<br/>uses local user.name / user.email<br/>no co-author / URL trailers"]
        C --> P["git push origin main"]
    end

    P --> GH["GitHub: push event on main"]

    subgraph CI["GitHub Actions — .github/workflows/deploy.yml"]
        GH --> J1["checkout + setup-node 22"]
        J1 --> J2["npm ci"]
        J2 --> J3["npm run build:web<br/>esbuild bundles src/ engine + web/ adapter"]
        J3 --> J4["dist/ = index.html, app.js,<br/>style.css, backend.js"]
        J4 --> J5["upload-pages-artifact"]
        J5 --> J6["deploy-pages"]
    end

    J6 --> SITE["https://kdbrian.github.io/Seevy/"]

    subgraph Full["Full build (unaffected by Pages)"]
        FS["npm start / docker compose up"] --> SRV["Express + node:sqlite<br/>+ optional Claude review"]
    end
Loading

Data & backups

What Server build Static build
Versions, metrics, saved reviews data/seevy.db localStorage["seevy.v1"]
Original uploaded files data/uploads/ not kept

Use backup ▾ in the sidebar to download a JSON snapshot of every version (text + reviews) or import one back — the format is identical across builds, so it's also how you move history between the two.


Project layout

server.js                Express API + static host + tiny .env loader
src/
  db.js                  node:sqlite storage (server build)
  normalize.js           shared text tidy-up
  extract.js             file -> text: pdf-parse, mammoth (server build)
  analyze.js             per-version heuristics, CV-health score, ATS audit, inferDate
  misfits.js             cross-version regression / inconsistency detection
  diff.js                word / line diff
  curator.js             bullet clustering + Markdown export
  ai.js                  optional Claude review layer (server build)
public/
  index.html
  app.js                 single-page UI (ES module) — build-agnostic
  backend.js             server adapter: talks to /api/*
  style.css              untogglable brutalist light theme
web/src/
  backend-local.js       browser adapter: runs the engine against localStorage
  store.js               localStorage persistence
  parse.js               in-browser pdf.js / mammoth (lazy-loaded)
scripts/
  build-web.mjs          esbuild bundle + copies -> dist/ (index.html is
                         generated from public/index.html with relative paths)
dist/                    build output (gitignored) — what GitHub Pages serves
.github/workflows/
  deploy.yml             build + deploy to GitHub Pages on push to main

public/app.js never talks to a server directly — it only calls the backend object it imports from ./backend.js. The server build ships the fetch adapter; build-web.mjs swaps in the localStorage adapter. Add a feature once in the engine and both builds get it.


How the scores work

CV‑health (src/analyze.js) rolls up: quantified‑bullet ratio, action‑verb ratio, weak openers (“responsible for…”), buzzword load, passive voice, first‑person usage, long sentences, section coverage, verb repetition, length fit, contact completeness. The per‑factor breakdown is shown on each version.

ATS readiness checks structure a parser cares about: standard headings, machine‑readable contact block, single column, parser‑safe characters, skills as text (not rating bars), consistent date ranges, reverse‑chronological order, acronyms expanded once, bulleted experience, length band, file format, no header/footer content. Each failing check carries a specific fix.

Both are heuristics — a sanity check you watch move as you edit, not a verdict.

Limitations

  • Parsing is structure‑blind: there's no per‑role/date model, so “weakened bullet” and “lost achievement” are fuzzy token‑overlap matches.
  • Legacy binary .doc is best‑effort — export DOCX or a text‑based PDF.
  • The static build needs a working CDN for PDF/DOCX parsing; if it's blocked, paste the text instead. Plain text and Markdown always work.
  • Fonts load from Google Fonts when online and fall back to system fonts offline.

License

MIT — see LICENSE if present, otherwise treat this as MIT.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages