An intelligent job application tracking system that automatically scans your Gmail, classifies recruitment emails using AI, and helps you keep track of your job applications throughout the entire hiring process.
- Gmail Integration: Connect your Gmail account via OAuth2
- Automatic Scanning: Built-in cron job scans your inbox every 5 minutes
- Smart Classification: Uses Google Gemini Flash Lite to classify emails into:
RECRUITMENT_ACK- Application acknowledgmentNEXT_STEP- Interview invites, assessments, next stagesDISAPPROVAL- Rejections, position filled
- Timeline View: See all interactions with each company in chronological order
- Status Management: Track applications through stages: Applied β Acknowledged β Screening β Rejected/Hired
- Company & Position Extraction: Automatically extracts job details from emails
- Manual Applications: Add applications manually that weren't sent via email
- Auto-Labeling: Automatically applies labels to your Gmail threads based on classification
- Label Creation: Creates labels automatically if they don't exist
- Confidence Indicators: Low-confidence emails get a special label for review
- Job Queue: Uses PG-Boss for reliable background job processing
- Retry Logic: Failed jobs are automatically retried with exponential backoff
- Dashboard: Overview of all your applications with status filters
- Application Detail View: Complete history of all emails and events for each application
- Merge Applications: Merge duplicate applications for the same position
- Manual Sync: Trigger manual email sync from a specific date
- Real-time Status: See sync progress and queue statistics
Frontend:
- React 19 + TypeScript
- TanStack Router (type-safe routing)
- TanStack Query (data fetching)
- Tailwind CSS + shadcn/ui components
- tRPC client (type-safe API calls)
- Vite (build tool)
Backend:
- Hono (fast, lightweight web framework)
- tRPC (type-safe API)
- Better Auth (authentication)
- PG-Boss (PostgreSQL-based job queue)
- Google APIs (Gmail + Gemini)
Database:
- PostgreSQL
- Drizzle ORM (type-safe queries)
AI:
- Google Gemini Flash Lite (email classification)
.
βββ apps/
β βββ web/ # Frontend React app
β β βββ src/
β β β βββ components/ # UI components
β β β β βββ applications/ # Application-related components
β β β β βββ dashboard/ # Dashboard components
β β β β βββ ui/ # shadcn/ui components
β β β βββ routes/ # TanStack Router routes
β β β βββ hooks/ # Custom React hooks
β β β βββ lib/ # Utilities & tRPC client
β β βββ package.json
β β
β βββ server/ # Backend API server
β βββ src/
β β βββ db/ # Database schemas & migrations
β β βββ jobs/ # Background job handlers
β β β βββ handlers/ # Job implementations
β β β β βββ process-email.ts # Fetch email from Gmail
β β β β βββ analyze-content.ts # Classify with Gemini
β β β β βββ label-email.ts # Apply Gmail labels
β β β βββ pgboss.ts # Job queue setup
β β β βββ schedule.ts # Cron jobs
β β βββ routers/ # tRPC routers
β β βββ services/ # Business logic
β β β βββ gmail-service.ts # Gmail API client
β β β βββ email-classifier.ts # Gemini classification
β β β βββ job-tracking-service.ts # Application tracking logic
β β βββ index.ts # Server entry point
β βββ package.json
β
βββ turbo.json # Turborepo configuration
βββ package.json # Root package.json
Gmail API
β
ββββΊ Cron Job (every 5 min) βββΊ List new messages
β
βΌ
βββββββββββββββββββββββ
β PG-Boss Queue β
β β
β 1. process-email ββββΊ Fetch email from Gmail
β 2. analyze-content ββββΊ Classify with Gemini
β 3. label-email ββββΊ Apply Gmail labels
βββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β PostgreSQL DB β
β β
β job_applications β
β application_events β
β application_notes β
βββββββββββββββββββββββ
- Node.js 18+
- PostgreSQL database (or Docker)
- Google Cloud project with Gmail API enabled
- Gemini API key
# Clone the repository
git clone https://github.com/Soif2Sang/TrackApply
cd TrackApply
# Install dependencies
npm installCopy .env.example to .env in the root directory and fill in your values:
cp .env.example .env# Start PostgreSQL (using Docker)
cd apps/server
npm run db:start
# Push database schema
npm run db:push- Go to Google Cloud Console
- Create a new project or select existing
- Enable the Gmail API
- Create OAuth 2.0 credentials (Web application type)
- Add authorized redirect URI:
http://localhost:3002/auth/gmail/callback - Copy Client ID and Client Secret to your
.env
# From root directory
npm run devThe app will be available at:
- Frontend: http://localhost:3003
- Backend: http://localhost:3002
- Sign up / Sign in to the application
- Go to settings and configure your Gmail OAuth credentials
- Click "Connect Gmail" and authorize the application
- The system will start scanning your emails every 5 minutes
# Development (from root)
npm run dev # Start all apps in development mode
npm run dev:web # Start frontend only
npm run dev:server # Start backend only
# Build
npm run build # Build all apps
# Database (from apps/server)
npm run db:push # Push schema changes to database
npm run db:generate # Generate migrations
npm run db:migrate # Run migrations
npm run db:studio # Open Drizzle Studio
npm run db:start # Start PostgreSQL in Docker
npm run db:stop # Stop PostgreSQL| Variable | Description | Default |
|---|---|---|
EMAIL_SYNC_BATCH_SIZE |
Emails to process per batch | 50 |
EMAIL_SYNC_PAGE_SIZE |
Page size for Gmail API queries | 100 |
EMAIL_SYNC_MAX_TOTAL |
Max emails per sync (0 = unlimited) | 0 |
EMAIL_SYNC_MAX_AGE_DAYS |
How far back to sync emails | 90 |
| Variable | Description | Default |
|---|---|---|
PROCESS_EMAIL_CONCURRENCY |
Parallel email fetching | 2 |
ANALYZE_CONTENT_CONCURRENCY |
Parallel AI classification | 2 |
LABEL_EMAIL_CONCURRENCY |
Parallel label operations | 4 |
ANALYZE_RETRY_LIMIT |
Max retries for AI calls | 5 |
ANALYZE_RETRY_DELAY_SECONDS |
Delay between retries | 30 |
The system uses Google Gemini Flash Lite by default (cheap and fast). You can change the model:
GEMINI_MODEL=gemini-2.5-flash-lite- All Gmail tokens are encrypted at rest using AES-256
- OAuth2 flow with refresh tokens
- Automatic token refresh before expiry
- No email content stored permanently (only metadata)
- Check Gmail connection status in the UI
- Verify cron job is running (check server logs)
- Check PG-Boss job queue status
- Review emails marked with "LOW_CONFIDENCE" label
- Adjust the system prompt in
email-classifier.ts - Try a different Gemini model
- Gmail API has quota limits
- The system includes retry logic with exponential backoff
- Reduce
EMAIL_SYNC_BATCH_SIZEif needed
cd apps/server
npm run compile # Compiles to standalone binary with Buncd apps/web
npm run build # Builds to dist/ folderdocker-compose up -d # Starts PostgreSQLMIT
