Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Career Copilot

Upload a resume and paste a job posting. Get a fit score, a matched/missing/extra skills breakdown visualized in 3D, and a Claude-tailored rewrite of the resume aimed at that specific job.

Portfolio piece #5 (of 5, final app) -- back on TypeScript/Next.js, closing out the portfolio on the stack used in 3 of the 5 apps.

Architecture

  • Next.js 16 (App Router) + TypeScript + Tailwind, deployed on Vercel
  • Neon Postgres via Prisma 7 + @prisma/adapter-pg -- Resume and JobPosting each have many Analysis rows (one per pairing)
  • unpdf for PDF resume text extraction (zero native deps, unlike pdf-parse/pdfjs-dist)
  • Claude Fable 5 (lib/ai/analyze-fit.ts) does one grounded call per analysis: given the resume text and job posting text (both ground truth, never invented), it returns a fit score, matched/missing/resume-only skill lists, and a tailored resume rewrite -- as a single JSON object parsed with a defensive markdown-fence strip + try/catch, since every failure mode must surface a real error rather than fail silently
  • 3D skill-space view (components/skill-space-scene.tsx): skills positioned by lib/skills/layout.ts around three fixed cluster centers (matched/missing/resume-only) with a deterministic hash-based jitter per skill name (not Math.random(), so the layout is stable across re-renders rather than reshuffling every time), colored with a reserved status-style palette (green/red/gray) since cluster membership is state, not a category
  • GitHub OAuth via Auth.js v5
  • GitHub Actions CI (lint, typecheck, unit tests, migrate against a real Postgres service, build, smoke test) gating merges to main; Vercel's Git integration handles the actual deploy

Local setup

Requires Node 24+.

npm install
cp .env.example .env.local   # fill in as you go through the steps below

1. Database (Neon)

  1. Create a project at neon.tech. Copy the pooled connection string into DATABASE_URL and the unpooled one into DIRECT_URL.
  2. npx prisma migrate deploy.

2. GitHub OAuth

  1. GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.
  2. Homepage URL: http://localhost:3000. Authorization callback URL: http://localhost:3000/api/auth/callback/github (and your Vercel domain's equivalent for production -- GitHub OAuth Apps only support one callback URL at a time, so update this same field after deploying rather than creating a second app).
  3. Fill in AUTH_GITHUB_ID / AUTH_GITHUB_SECRET. Generate AUTH_SECRET with openssl rand -base64 32.

3. Anthropic

Get a key from the Anthropic Console, set ANTHROPIC_API_KEY. Claude Fable 5 requires the org's data retention to be 30+ days -- a zero-data-retention org gets a 400 on every request.

4. PostHog (optional)

Set NEXT_PUBLIC_POSTHOG_KEY / NEXT_PUBLIC_POSTHOG_HOST if you want analytics locally. Safe to leave blank -- calls no-op without a key.

Run it

npm run dev

Testing

npm run test        # unit tests -- lib/skills/layout.ts, pure fixtures, no DB
npm run typecheck
npm run lint
npm run build

lib/skills/layout.ts is unit-tested with no database or network dependency. Everything that touches Postgres or Claude is exercised by CI's smoke test and manual end-to-end testing (scripts/manual-verify.ts), not vitest -- files that import "server-only" throw under plain Node, so they can't be unit-tested directly.

Deployment

Push to GitHub, import the repo on Vercel, and add every variable from .env.example. Vercel deploys automatically on every push to main (production) and every PR (preview); CI in .github/workflows/ci.yml gates merges to main via branch protection but does not itself deploy.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages