A chat-first, multi-agent career platform. Ask it anything about your job search — in plain English — and it finds roles, drafts cold emails, surfaces learning resources, tracks your applications, and applies on your behalf.
Live: master.d1qwe99cpev8tx.amplifyapp.com
Version: v2.4.0
- Security: bcrypt password hashing (transparent migration from legacy SHA-256); DB-backed single-use password reset tokens; HTML-escaped email bodies;
/reset-passwordand/onboard/parse-resumerate-limited. - Data safety: removed startup
DROP TABLEof cold-email tables (root cause of data loss across deploys); account-delete cascade now covers all user-owned tables. - Job feed: qualitative match labels (Strong / Good / Worth a Shot / Long Shot) instead of raw percentages, inline matching/missing skills on each card, guest feed no longer 500s.
- India sources: cleaned dead Greenhouse slugs (Razorpay/Freshworks/etc. moved off Greenhouse); Indeed RSS replaced with Indeed-via-JSearch India route. Working without keys: PhonePe + Groww + Postman (Greenhouse), Meesho + Paytm (Lever). Set
JSEARCH_API_KEYand/orADZUNA_APP_ID+ADZUNA_APP_KEYfor full Indeed/Adzuna India coverage. - UX: AI chat thinking indicator, stable AI input (no shrink-on-focus), profile shows existing resume instead of re-prompting, More-menu dropdown solid background, job detail page hides AI actions for aggregator-source jobs.
Type a message. The platform routes it to the right agent, streams a response in real-time, and embeds structured data (jobs, emails, articles) directly in the chat.
"Find remote Python jobs over 150k"
→ Job Search Agent returns ranked matches, streamed live
"Write a cold email for the Staff Engineer role at Stripe"
→ Email Generator reads your resume + job description, generates personalised email
"What skills am I missing for ML engineering roles?"
→ Resume Intelligence Agent compares your profile against market requirements
"Find articles about system design interviews"
→ Blog Discovery Agent searches curated article database, returns recommendations
| Feature | Description |
|---|---|
| AI Chat | Conversational interface routes queries to specialised agents |
| Job Feed | 2,400+ curated jobs with AI match scoring against your profile |
| AI Job Search | Natural language → structured filters → ranked results |
| Cold Email Generator | Personalised outreach emails drafted from your resume + job description |
| Application Tracker | Kanban board to manage your job pipeline |
| Salary Intelligence | Market rate data for any role, location, and experience level |
| Job Alerts | Save searches and receive email notifications for new matches |
| Auto-Apply | Automated application submission with configurable rules |
| ATS Scanner | Resume-to-job-description keyword gap analysis |
| Analytics | Application funnel metrics and performance dashboard |
| Blog Discovery | Curated tech and career articles with bookmarking |
| Gmail Integration | Send cold emails directly from your Gmail account |
| Profile Builder | Resume upload (PDF/DOCX), skill extraction, career preferences |
User Message
│
▼
┌─────────────────────────────┐
│ Safety Agent │ ← PII detection, rate limiting, content moderation
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Intent Router │ ← Classifies: job_search | email_draft | resume_query
│ (OpenAI GPT-4o-mini) │ blog_search | followup | salary_estimate |
└──────────────┬──────────────┘ skill_gap | interview_prep | general
│
┌─────────┼─────────┬──────────┬───────────┐
▼ ▼ ▼ ▼ ▼
┌─────────┐ ┌───────┐ ┌────────┐ ┌──────┐ ┌──────────┐
│ Job │ │ Email │ │Resume │ │ Blog │ │ General │
│ Search │ │ Gen │ │ Intel │ │Disco │ │ Agent │
└────┬────┘ └───┬───┘ └───┬────┘ └──┬───┘ └────┬─────┘
│ │ │ │ │
└─────────┴──────────┴──────────┴───────────┘
│
▼
┌────────────────────────┐
│ Personalization Agent │ ← Tailors response to user profile
│ Ranking Agent │ ← Scores/orders results
└────────────┬───────────┘
│
▼ SSE stream
chunks | jobs_data | email_data
articles_data | quick_actions | complete
Every response streams multiple event types to the frontend:
event: thinking → "Searching for Python roles..."
event: chunk → text content, token by token
event: jobs_data → [{job_id, title, company, salary, match_score}, ...]
event: email_data → {subject, body, tone, word_count}
event: articles_data → [{title, url, category, reading_time}, ...]
event: quick_actions → ["Save All Jobs", "Send Email", "Bookmark"]
event: complete → {conversation_id, message_id}
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 14, React 18, TypeScript | App Router, SSR |
| UI | TailwindCSS, Lucide Icons | Dark theme, glass morphism |
| State | Zustand | Chat state, SSE stream management |
| Backend | FastAPI 0.115, Python 3.11 | Async REST + SSE API |
| ASGI | Uvicorn, asyncpg | Async server + PostgreSQL driver |
| LLM | OpenAI GPT-4o (quality) + GPT-4o-mini (speed) | Agent inference |
| Orchestration | LangGraph | Agent state machine, handoffs |
| Chains | LangChain | Tool integration |
| Database | Supabase (PostgreSQL) | Users, jobs, chats, articles |
| Auth | Supabase Auth + JWT + Google OAuth | Email/password + OTP + OAuth |
| Storage | Supabase Storage | Resume PDFs |
| Queue | Celery + Redis | Background job/article scraping |
| Scraping | Playwright, BeautifulSoup4 | Job + article sources |
| PDF Parsing | PyPDF2, PDFPlumber, python-docx | Resume parsing |
| Gmail API (OAuth) | Send cold emails from user's Gmail | |
| Deployment | AWS Lambda + Mangum / AWS Amplify | Serverless backend + frontend |
| Agent | Intent Categories | What It Does |
|---|---|---|
| Safety | (all, first) | PII redaction, content moderation, per-user rate limiting |
| Intent Router | (all) | Classifies message into 10 intent types, extracts entities |
| Job Search | job_search |
Natural language → DB query + live JSearch API fallback, match scoring |
| Email Generator | email_draft |
Reads user profile + job description, generates personalised cold email |
| Resume Intelligence | resume_query, skill_gap |
Profile analysis, skill gap detection vs. target roles |
| Blog Discovery | blog_search |
Searches article DB by keywords/skills, trending scores |
| Followup Scheduler | followup |
Application tracking, reminder scheduling |
| General | general, fallback |
Greetings, ambiguous queries, platform guidance |
| Personalization | (companion) | Tailors response language/depth to user's experience level |
| Ranking | (companion) | Scores and orders results before returning to user |
ai-career-copilot/
├── backend/
│ └── app/
│ ├── main.py # FastAPI entry, route registration, lifespan
│ ├── core/
│ │ ├── config.py # Pydantic Settings (all env vars)
│ │ ├── database.py # AsyncPG engine, session factory, init_db()
│ │ ├── auth.py # JWT, OAuth, OTP, password hashing
│ │ └── llm.py # LLM client factory (GPT-4o / GPT-4o-mini)
│ ├── agents/
│ │ ├── orchestrator.py # LangGraph StateGraph coordinator
│ │ ├── intent_router.py # 10-category intent classifier + entity extraction
│ │ ├── job_search_agent.py
│ │ ├── email_generator_agent.py
│ │ ├── resume_intelligence.py
│ │ ├── blog_discovery_agent.py
│ │ ├── followup_scheduler.py
│ │ ├── general_agent.py
│ │ ├── safety_agent.py
│ │ ├── personalization_agent.py
│ │ ├── ranking_agent.py
│ │ └── tools/ # Job APIs, scrapers, mock data
│ ├── api/v1/
│ │ ├── auth.py # Register, login, OTP, Google OAuth
│ │ ├── chat.py # POST /chat/stream (SSE), conversation management
│ │ ├── profile.py # Resume upload/parse, career preferences
│ │ ├── jobs.py # Job search, CRUD, company cards, referral packages
│ │ ├── discovery.py # Job feed, AI search, saved searches
│ │ ├── applications.py # Job application status tracker
│ │ ├── analytics.py # Application funnel metrics
│ │ ├── alerts.py # Saved search alerts (CRUD)
│ │ ├── salary.py # Salary intelligence by role/location/experience
│ │ ├── auto_apply.py # Auto-apply queue, results, settings
│ │ ├── ats.py # ATS resume scanner
│ │ ├── cold_emails.py # Email drafts, templates
│ │ ├── gmail.py # Gmail OAuth, send endpoint
│ │ ├── templates.py # Email templates
│ │ ├── blog.py # Articles, bookmarks, trending
│ │ └── pipeline.py # 7-agent pipeline routes
│ ├── models/ # SQLAlchemy ORM (User, Job, Chat, Blog, ColdEmail)
│ ├── schemas/ # Pydantic request/response models
│ ├── services/ # Business logic (13+ services)
│ └── lambda_handler.py # AWS Lambda entry (Mangum)
│
├── frontend/
│ └── app/
│ ├── page.tsx # Landing page (AI prompt bar, features, footer)
│ ├── layout.tsx # Root layout (ChatWidget on every page)
│ ├── login/page.tsx # Email/password + Google OAuth login
│ ├── register/page.tsx # Registration with OTP email verification
│ ├── jobs/page.tsx # Job feed with AI search + advanced filters
│ ├── jobs/[id]/page.tsx # Job detail (description, match breakdown, apply)
│ ├── ai/page.tsx # Full-page chat interface
│ ├── applications/page.tsx # Kanban application tracker
│ ├── analytics/page.tsx # Application metrics dashboard
│ ├── alerts/page.tsx # Saved search alerts manager
│ ├── auto-apply/page.tsx # Auto-apply queue, results, settings
│ ├── cold-emails/page.tsx # Cold email history + compose
│ ├── blog/page.tsx # Article feed with filters + bookmarks
│ ├── profile/page.tsx # Resume upload, skills, market rate widget
│ └── settings/ # Gmail OAuth settings
│
├── frontend/components/
│ ├── Navigation.tsx # App-wide nav with mobile hamburger
│ ├── AIPromptBar.tsx # Sticky AI search bar (jobs, blog pages)
│ ├── ArticleCard.tsx # Blog article card with bookmark toggle
│ ├── OnboardingModal.tsx # First-visit onboarding (landing page only)
│ ├── SkeletonLoader.tsx # Loading skeletons (JobCard, KanbanColumn, etc.)
│ ├── Tooltip.tsx # Hover tooltip wrapper
│ └── chat/ # ChatWidget, MessageBubble, QuickActions
│
├── frontend/lib/
│ └── api.ts # Centralized fetch client with auth headers + retry
│
├── frontend/stores/
│ └── chatStore.ts # Zustand: messages, SSE stream, widget open state
│
├── e2e-comprehensive-test.js # 26-test Playwright E2E suite
├── E2E_BUG_REPORT.md # Latest automated test report
├── docker-compose.yml
└── README.md
- Python 3.11+
- Node.js 20+
- Docker (for Redis)
- Supabase project (supabase.com)
- OpenAI API key (platform.openai.com)
git clone https://github.com/Priyank032/ai-career-copilot.git
cd ai-career-copilot
# Backend
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
# Frontend
cd ../frontend
npm installbackend/.env
# Database
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/dbname
SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_anon_key
SUPABASE_SERVICE_KEY=your_supabase_service_key # for admin operations
# AI
OPENAI_API_KEY=your_openai_api_key
OPENAI_MODEL_HIGH=gpt-4o # quality-critical tasks
OPENAI_MODEL_FAST=gpt-4o-mini # high-frequency tasks
# Auth
SECRET_KEY=your_jwt_secret_min_32_chars
ALGORITHM=HS256
# Google OAuth (for Gmail integration + Google sign-in)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Email (OTP verification)
SMTP_HOST=smtp.gmail.com
SMTP_USER=your_sender_email
SMTP_PASSWORD=your_app_password
# Redis (Celery broker)
REDIS_URL=redis://localhost:6379
# Job APIs (optional — system falls back to DB if missing)
JSEARCH_API_KEY=your_rapidapi_key # for live job search fallbackfrontend/.env.local
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_keySchema is initialised automatically on first run via SQLAlchemy create_all(). For Supabase, enable the pgvector extension:
-- In Supabase SQL Editor
CREATE EXTENSION IF NOT EXISTS vector;# Terminal 1: Redis (required for Celery)
docker run -p 6379:6379 redis:7-alpine
# Terminal 2: Backend
cd backend
uvicorn app.main:app --reload --port 8000
# Terminal 3: Celery worker (background job/article fetching)
cd backend
celery -A app.tasks worker --loglevel=info
# Terminal 4: Frontend
cd frontend
npm run devOpen http://localhost:3000
POST /api/v1/chat/stream
Authorization: Bearer {token}
{ "conversation_id": "uuid|null", "message": "Find remote Python jobs over 150k" }
→ text/event-stream
event: thinking data: {"content": "Searching job database..."}
event: chunk data: {"content": "I found 14 roles...", "agent": "job_search"}
event: jobs_data data: {"jobs": [...], "total": 14}
event: complete data: {"conversation_id": "uuid", "message_id": "uuid"}
POST /api/v1/auth/register Email + OTP registration
POST /api/v1/auth/login JWT login
GET /api/v1/auth/google/callback Google OAuth
GET /api/v1/discovery/feed Personalised job feed (scored, paginated)
POST /api/v1/discovery/ai-search Natural language job search
GET /api/v1/jobs/{id} Job detail
POST /api/v1/jobs/search Structured job search (POST)
GET /api/v1/alerts/saved-searches List saved search alerts
POST /api/v1/alerts/saved-searches Create alert from current filters
DELETE /api/v1/alerts/saved-searches/{id} Delete alert
GET /api/v1/profile User profile + resume data
POST /api/v1/profile/resume Upload resume (PDF/DOCX → parsed skills/exp)
GET /api/v1/salary/intelligence Market rate by role, location, experience
POST /api/v1/ats/scan ATS keyword gap analysis
GET /api/v1/applications Application list with status
POST /api/v1/applications Create application
GET /api/v1/analytics/dashboard Funnel metrics (applied/interview/offers)
GET /api/v1/auto-apply/queue Jobs queued for auto-application
GET /api/v1/auto-apply/results Completed auto-apply history
GET /api/v1/auto-apply/settings Current auto-apply configuration
PUT /api/v1/auto-apply/settings Update rules (daily limit, match threshold, etc.)
POST /api/v1/cold-emails Save email draft
GET /api/v1/cold-emails List drafts
POST /api/v1/cold-emails/{id}/send Send via Gmail
GET /api/v1/blog/articles Article feed (paginated, filterable)
POST /api/v1/blog/{id}/bookmark Bookmark article
- AI chat end-to-end (intent classification → agent → SSE stream)
- Job feed with 2,400+ jobs, AI match scoring, advanced filters
- Natural language AI job search
- Cold email generation and Gmail send
- Resume upload, parsing, skill extraction
- Salary intelligence (market rate by role/location/experience)
- Job alerts (saved searches with CRUD)
- Auto-apply configuration and queue management
- ATS resume scanner
- Application tracker (kanban board)
- Analytics dashboard
- Article discovery with bookmarking
- Authentication (email+OTP, Google OAuth, JWT)
- Conversation history and persistence
- Mobile-responsive UI with hamburger menu
- Background job/article fetching via Celery
- Auto-apply execution — Queue management works; actual browser-based form submission requires Playwright in non-Lambda mode
- OTP store is in-memory — Lost on server restart; use Redis-backed store for production
- No LLM fallback — If OpenAI is down, chat is unavailable
- Gmail token refresh — OAuth tokens expire after 1 hour; auto-refresh requires a background task
- Celery requires Redis — Background scraping won't run without Redis; API still works without it
# Backend
cd backend
uvicorn app.main:app --reload # Dev server
black app/ # Format
ruff check app/ # Lint
# Frontend
cd frontend
npm run dev # Dev server
npm run build # Production build
npm run lint # ESLint
# E2E Tests (Playwright)
node e2e-comprehensive-test.js # Runs 26-test suite, outputs E2E_BUG_REPORT.mdBackend → AWS Lambda
# lambda_handler.py
from mangum import Mangum
from app.main import app
handler = Mangum(app)Build and push to ECR, configure Lambda with env vars. Set LAMBDA_RUNTIME=true.
Frontend → AWS Amplify
Set NEXT_PUBLIC_API_URL to your Lambda function URL (via API Gateway or Function URL). Amplify auto-detects Next.js and builds with output: 'standalone'.
Built by Priyank Agrawal