A private job-search command center. It finds high-fit roles, explains every score, and builds truthful application packages from a verified Claim Ledger. It tracks each application through an immutable audit trail and measures what actually produces interviews.
North-star metric: qualified interviews booked, not application volume.
Demo data: until you connect a live source, the app loads fictional postings from employers like “Harborline Bank (Demo)”. They carry a DEMO label everywhere, and “submissions” to them are simulated (confirmation
DEMO-SIM-…). Nothing leaves the app.
npm install
npm run dev # http://localhost:3000
With no environment variables set, the app runs entirely on your machine:
| Concern | Local mode |
|---|---|
| Database | Embedded Postgres (PGlite) with pgvector, stored in .data/pglite |
| Auth | Single-user workspace bound to this machine |
| Files | Encrypted (AES-256-GCM) in .data/files; the key is generated in .data/local.key |
| Jobs | Demo source plus any Greenhouse, Lever, or Ashby boards you connect |
Drafts work locally (copy, mailto:, .eml download) |
Onboarding walks you through these steps:
Run only one process against a PGlite directory at a time. Use Settings → Run worker now locally.
npm run workeris meant for a Postgres (DATABASE_URL) deployment.
| Command | Purpose |
|---|---|
npm run dev |
Dev server |
npm test |
Unit and integration tests (Vitest; the integration suite runs on in-memory Postgres) |
npm run typecheck |
TypeScript |
npm run lint |
ESLint |
npm run db:migrate |
Apply migrations to DATABASE_URL, or to local PGlite if unset |
npm run worker / worker:once |
Background worker loop (self-hosted Postgres deployments) |
npm run build && npm start |
Production build |
.env.example to .env.local (or your host’s env settings) and fill in:
DATABASE_URL: the Supabase Transaction pooler connection string.NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY.APP_ENCRYPTION_KEY, generated with:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
APP_URL (your deployed URL) and CRON_SECRET (any long random string).npm run db:migrate
This applies db/migrations/*.sql and, because Supabase is configured, db/migrations/supabase/*.sql: row-level security on every table, a private documents storage bucket, and OAuth tokens that are never exposed through the Data API.
{APP_URL}/auth/callback to the redirect URLs. Disable public sign-ups once your own account exists.vercel.json schedules /api/worker every 15 minutes. Vercel sends Authorization: Bearer $CRON_SECRET automatically.https://www.googleapis.com/auth/gmail.compose, redirect {APP_URL}/api/oauth/google/callback.Mail.ReadWrite Mail.Send offline_access openid email, redirect {APP_URL}/api/oauth/microsoft/callback.Moving from local to Supabase: set the env vars, run npm run db:migrate, then re-upload your resume. Local data in .data/ is not migrated automatically. Use Settings → Export if you want a copy.
| Capability | Status |
|---|---|
| Resume upload and parsing (PDF/DOCX), Claim Ledger, versioned master and lane resumes | Live |
| Prompt-injection detection on resumes, job descriptions, and pasted/fetched content | Live |
| Greenhouse, Lever, and Ashby public job-board APIs; manual URL import (ATS links and schema.org JobPosting pages; paste for aggregators) | Live, read-only |
| Dedupe, freshness verification, Fit/Confidence/Priority scoring, Workbench | Live |
Tailored packages with evidence check and diff; .docx/.txt export |
Live |
| Automatic drafts for Apply Now / Strong Review matches (resume, JD-matched cover letter, answers, hiring-manager intro email), capped per day; drafts only | Live (Settings → Automatic drafts) |
| ATS keyword match: posting terms present / truthfully addable (proved by a verified fact) / gaps, with one-click add and rebuild | Live |
| Hiring-manager finder: likely manager titles from the reporting line and level, names/emails the posting publishes, LinkedIn/Google search links you open | Live, guided (no scraping, no guessed emails) |
| Copilot apply: deep link, copy-ready answers, idempotent submission record | Live (you submit on the employer site) |
| Guarded Auto-Apply | Engine live; only the demo connector is SUPPORTED, and its submissions are simulated. Real ATS application APIs require employer credentials, so every live source is MANUAL_ONLY. |
| Gmail/Outlook provider drafts and optional send | Live once OAuth credentials are configured; otherwise local drafts only |
| Scheduled searches, stage-aging alerts, durable queue | Live via cron/worker |
| Response/status detection from the inbox | Not implemented (the Gmail scope is compose-only by design) |
src/lib/engine/gate.ts). Automation always stops for review on:
SUPPORTED.Fit (0–100):
| Component | Points |
|---|---|
| Must-have coverage | 24 |
| Role family | 18 |
| Transferable competencies | 14 |
| Seniority/scope | 12 |
| Domain | 10 |
| Outcomes | 8 |
| Location | 5 |
| Compensation | 4 |
| Freshness | 3 |
| Source | 2 |
Requirement weights are core-required ×3, required ×2, and preferred ×1. Evidence earns 1.0 (exact), 0.75 (strong transferable), 0.4 (adjacent), or 0 (none).
Confidence (description completeness, pay/location clarity, parse certainty, and evidence coverage) and Priority are computed separately. Recommendation tiers and auto-apply thresholds follow the product spec. After 20 resolved outcomes, Insights proposes reversible weight changes within ±15% of the defaults.
db/migrations/ SQL (portable core + supabase/ hardening)
src/lib/engine/ Pure logic: parsing, taxonomy, scoring, dedupe, evidence, packages, outreach, gate, metrics, calibration
src/lib/server/ Data access & services (profile, jobs, packages, applications, outreach, autoapply, queue, insights, mail, storage)
src/lib/sources/ Source adapters + demo data
src/app/(app)/ Overview, Job Radar, Workbench, Review Queue, Applications, Outreach, Profile & Assets, Insights, Settings
src/app/api/ Export, resume download, OAuth, worker, .eml
tests/ Engine unit tests + end-to-end integration test