A multi-tenant hiring dashboard for syncing applicant emails, ranking candidates against job criteria, and managing your recruiting pipeline.
Connect Gmail to pull in resumes, score applicants against a configurable YAML rubric, review PDFs and GitHub profiles, shortlist top talent, and send outreach — all in one workspace. Built with TanStack Start, Supabase (Postgres + Auth + Storage), Drizzle ORM, and Gmail OAuth. Deploys to Vercel as a single full-stack app.
Features · Tech Stack · Getting Started · Deploy
- Organization-scoped workspace — multi-tenant data with Supabase RLS
- Dashboard overview — total applicants, GitHub/resume counts, starred candidates, pipeline status
- Candidate table — search, filter by status/starred/GitHub, sort, pagination
- Pipeline statuses — new, shortlisted, interview, rejected, hired with notes and tags
- Connect Gmail via OAuth in Settings — encrypted refresh token storage
- Fetch applicant emails matching a configurable Gmail query
- Extract resume PDFs from attachments into Supabase Storage
- Sync panel — fetch, extract, or run a full sync from the UI
- Job criteria editor — YAML rubric (
config/job-criteria.yaml) for role, tech stack, and scoring weights - Filter panel — narrow the pool before ranking (location, experience, GitHub, etc.)
- Preview & rank — score candidates against criteria and save ranked reports
- Reports — browse and review past analysis runs
- Score breakdown — weighted criteria match with detailed breakdown
- Resume viewer — in-browser PDF preview via authenticated proxy
- GitHub insights — repo activity and profile enrichment (optional
GITHUB_TOKEN) - Link extraction — GitHub, LinkedIn, and portfolio URLs from email/resume
- Email outreach — preview and send shortlist emails from templates; batch send support
- Sign up / sign in via Supabase Auth (email + password)
- Per-org job criteria stored in Postgres
- Gmail connection management — connect, disconnect, sync status
| Layer | Technology |
|---|---|
| Runtime | Bun |
| Framework | TanStack Start + TanStack Router |
| UI | React 19, Tailwind CSS 4, Lucide icons |
| Database | Supabase Postgres |
| ORM | Drizzle ORM |
| Auth & storage | Supabase Auth + Storage (resumes & attachments) |
| Email sync | Gmail API via googleapis |
| PDF viewing | react-pdf + pdfjs-dist |
| Hosting | Vercel (Nitro preset) |
| Config | YAML job criteria + email templates in config/ |
- Bun (recommended) or Node.js 20+
- A Supabase project
- Google Cloud OAuth 2.0 Web application credentials (for Gmail sync)
- Optional: GitHub token for repo insights
git clone https://github.com/sprmke/job-applicants-analyzer.git
cd job-applicants-analyzer
bun install-
Create a Supabase project.
-
Apply migrations:
cd supabase supabase db push # or run each file from supabase/migrations/ in the SQL editor
-
Copy API keys from Project Settings → API.
cp .env.example .env.localFill in:
| Variable | Description |
|---|---|
SUPABASE_URL |
Supabase project URL |
SUPABASE_ANON_KEY |
Supabase anon key (server) |
SUPABASE_SERVICE_ROLE_KEY |
Service role key (server only — never expose to client) |
DATABASE_URL |
Supabase pooler connection string (see .env.example) |
VITE_SUPABASE_URL |
Same project URL (client) |
VITE_SUPABASE_ANON_KEY |
Same anon key (client) |
GOOGLE_OAUTH_CLIENT_ID |
Google OAuth client ID (Web) |
GOOGLE_OAUTH_CLIENT_SECRET |
Google OAuth client secret |
GOOGLE_OAUTH_REDIRECT_URI |
http://localhost:3000/api/gmail/callback |
TOKEN_ENCRYPTION_KEY |
Secret used to encrypt Gmail refresh tokens (any long random string) |
GITHUB_TOKEN |
Optional — GitHub API rate limits |
GMAIL_QUERY |
Optional — Gmail search query for applicant emails |
RECRUITER_TEAM_NAME |
Optional — used in outreach email templates |
See .env.example for the full list.
Google OAuth setup
- Enable the Gmail API in Google Cloud Console.
- Create OAuth credentials (Web application).
- Add authorized redirect URI:
http://localhost:3000/api/gmail/callback(and your production URL). - Paste client ID and secret into
.env.local.
Supabase Auth redirect
Add to Authentication → URL Configuration:
http://localhost:3000/auth/callbackhttps://your-app.vercel.app/auth/callback(production)
bun run devOpen http://localhost:3000 → sign up → dashboard.
If you have a local ./data/ folder from a previous filesystem workflow:
-
Sign up and copy your organization UUID from Supabase into
.env.local:ORGANIZATION_ID=your-org-uuid LOCAL_DATA_DIR=./data -
Run the import:
bun run migrate:local
Imports data/candidates/, SQLite notes/runs, and PDFs into Supabase Storage.
- Connect this repo — Root Directory is the repo root (no subdirectory).
- Framework: TanStack Start (via
vercel.json). - Set env vars from
.env.example(includingVITE_SUPABASE_*). - Gmail redirect:
https://your-app.vercel.app/api/gmail/callback - Supabase Auth redirect:
https://your-app.vercel.app/auth/callback
See docs/production-deployment.md for the full production checklist.
| Command | Description |
|---|---|
bun run dev |
Dev server on :3000 |
bun run build |
Production build |
bun run preview |
Preview production build locally |
bun run migrate:local |
Import ./data into Supabase |
bun run db:studio |
Drizzle Studio (database browser) |
bun run typecheck |
TypeScript check (tsc --noEmit) |
bun run generate-routes |
Regenerate TanStack Router routes |
config/ # job-criteria.yaml, email templates
data/ # local candidate PII (gitignored)
docs/ # architecture, deployment, migration history
scripts/ # migrate-local-data.ts
src/
db/ # Drizzle schema
server/ # business logic + TanStack server functions
components/ # UI (candidates, analyze, sync, settings)
routes/ # TanStack Router pages + API routes
lib/ # API client, Supabase config, utilities
supabase/ # Postgres migrations + RLS policies
vercel.json
| Route | Access | Description |
|---|---|---|
/ |
Auth | Dashboard with pipeline stats |
/login |
Public | Sign in |
/signup |
Public | Create account |
/auth/callback |
Public | Supabase auth callback |
/candidates/ |
Auth | Searchable candidate table |
/candidates/$slug |
Auth | Profile, score, resume, email |
/analyze/ |
Auth | Rank & analyze workspace |
/reports/ |
Auth | Saved analysis runs |
/reports/$id |
Auth | Report detail |
/sync/ |
Auth | Gmail sync panel |
/settings/ |
Auth | Gmail connect + job criteria |
/api/gmail/callback |
Public | Gmail OAuth callback |
/pdf-proxy/$slug/$filename |
Auth | Authenticated PDF proxy |
| Doc | Description |
|---|---|
docs/architecture.md |
System overview and tenancy model |
docs/migration-roadmap.md |
Historical migration notes |
docs/production-deployment.md |
Production deploy checklist |
docs/local-development.md |
Local dev setup |
Built for hiring teams who want applicant data, scoring, and outreach in one place — not scattered across inboxes and spreadsheets.