GitHub Repo

https://github.com/Wahid-Haidari/PitchPrep

Inspiration

Every semester, thousands of students walk into career fairs with the same generic pitch: "Hi, I'm a CS major, I'm interested in software engineering." We've been there ourselves — standing in line for 20 minutes, reaching the recruiter, and blanking on what to say. The conversation lasts 90 seconds, and it's over before it starts.

The real problem isn't that students don't care. It's that preparation is overwhelming. A typical career fair has 50–100 employers. Researching each one, tailoring a pitch, and figuring out which booths to prioritize takes hours that students don't have during midterm season.

We asked: what if AI could do the heavy lifting?

That's how PitchPrep was born — a platform that takes a student's profile and resume, researches every attending company, and generates a personalized game plan in minutes.

What it does

PitchPrep is a full-stack web application with two user roles:

For Students:

  • Upload a resume and fill out a profile (major, skills, location, work authorization, preferred roles)
  • Browse upcoming career fair events and see which companies are attending
  • Get an AI-generated Match Score (0–100%) for each company based on how well the student's background aligns
  • Click any company to receive a personalized Career Fair Card containing:
    • A 30-second elevator pitch written specifically for that student × company pair
    • 3 impressive "Wow Facts" about the company with sources
    • 2 smart questions to ask the recruiter
    • Top entry-level roles to mention
    • A follow-up email template
  • Generate pitches for all companies in batch, or clear and regenerate at any time

For Admins (Career Services):

  • Create career fair events with dates, locations, and descriptions

Match Score Algorithm

Each company is scored across 6 equally weighted categories:

$$\text{Match Score} = \frac{\sum_{i=1}^{6} S_i}{120} \times 100\%$$

where each $S_i \in [0, 20]$ represents:

$S_i$ Category What It Measures
$S_1$ Location Proximity of student to company HQ
$S_2$ Work Authorization Visa/sponsorship compatibility
$S_3$ Major Relevance Degree alignment with company needs
$S_4$ Job Type Role preference match (SWE, PM, DS, etc.)
$S_5$ Skills Technical skills overlap count
$S_6$ Resume Fit Overall resume relevance

The AI uses a multi-level scoring rubric with 5–8 thresholds per category to ensure differentiation between companies. For example, Skills matching uses:

$$S_5 = \begin{cases} 0 & \text{if } n = 0 \ 3 & \text{if } n = 1 \ 7 & \text{if } n = 2 \ 11 & \text{if } n = 3 \ 14 & \text{if } n = 4 \ 17 & \text{if } n = 5 \ 20 & \text{if } n \geq 6 \end{cases}$$

where $n$ is the number of matching skills between the student's profile and the company's valued skills.

How we built it

Frontend: Next.js 16 with React 19 and TypeScript. We used Tailwind CSS for styling with a custom design system (indigo primary, clean white cards, Geist font). The app uses client-side context providers for auth state and company data, with automatic refresh from the database on navigation.

Backend: Next.js API Routes acting as serverless functions. JWT authentication with bcrypt password hashing. RESTful endpoints for users, companies, events, and pitch generation.

Database: MongoDB Atlas with 5 collections — Users, Companies, Events, Pitches (with compound unique index on userId + companyId for upsert), and Employer Contexts (cached AI research to reduce API calls).

AI Pipeline: Two-stage OpenAI GPT-4o-mini pipeline:

  1. Employer Research — AI researches the company and returns structured context (what they do, valued skills, culture, wow facts)
  2. Pitch Generation — AI takes the student profile + employer context and generates a personalized career fair card with match scoring

We used $\text{temperature} = 0.5$ to balance creativity with consistency, and response_format: { type: "json_object" } for reliable structured output.

Key Technical Decisions:

  • Scores are generated on-demand (not pre-computed) so each user gets personalized results
  • Company data uses upsert with MongoDB's $set operator to avoid duplicate records
  • The frontend refreshes company data from MongoDB on every page load to ensure scores are always current
  • Pagination (5 per page) keeps the UI clean even with 50+ companies

Challenges we ran into

1. Match score inconsistency. Early on, the AI returned the same score for every company. We solved this by designing a detailed multi-level scoring rubric with explicit numerical thresholds for each category, and by adding company-specific context to the prompt (company size, location relative to student, sponsorship likelihood).

2. Score display bug. Our match score was on a 0–120 scale internally (6 categories × 20 points), but we displayed the raw number with a % symbol — so students saw "110% Match." We had to add the conversion $\frac{\text{raw}}{120} \times 100$ in four different UI components.

3. Database ID mismatches. When admins bulk-added companies, the frontend generated temporary IDs with Date.now(), but the API also generated IDs server-side. By the time the API ran, the timestamp had changed, so events pointed to IDs that didn't exist. We fixed this by making the API the single source of truth for ID generation.

4. Stale data on navigation. React's context preserved old company data when navigating between pages. After generating a pitch on the company detail page, going back to the event dashboard still showed blank scores. We added a refreshCompanies() function that fetches fresh data from MongoDB whenever the dashboard mounts.

5. Profile validation gaps. The pitch generation endpoint would fail with a cryptic error if the user hadn't completed their profile. We added explicit validation with clear error messages and ensured the seed script creates a complete demo user profile.

Accomplishments that we're proud of

  • The AI pipeline actually works. Getting GPT-4o-mini to return consistently structured, differentiated, and genuinely useful career fair content took serious prompt engineering. The pitches aren't generic — they reference specific company projects, align with the student's actual experience, and feel like something a real mentor would write.

  • The match score is meaningful. It's not a random number. The 6-category rubric with explicit thresholds produces scores that students can trust. A 92% match for Google vs. a 65% match for an unrelated company actually reflects real alignment — and students can see exactly why.

  • Full-stack, production-ready app. This isn't a prototype or a Figma mockup. PitchPrep has real authentication, a real database, real AI integration, admin tools, resume parsing, pagination, and batch operations. You can sign up, upload your resume, and walk into a career fair prepared — today.

  • One-click batch generation. A student can press "Generate All Pitches" and get personalized prep materials for every company at the fair. What used to take an entire weekend now takes 2 minutes.

  • Clean, intuitive UI. We built a custom component library (Button, Card, Badge, Modal, Input, Tabs, Stepper) with a consistent design language. The app looks and feels like a real SaaS product, not a hackathon project.

What we learned

  • Prompt engineering is iterative. Our first prompts were too generic. It took multiple rounds of adjusting temperature, adding scoring rubrics, and including company-specific instructions to get differentiated, useful results.

  • Optimistic UI updates are tricky. Updating the UI immediately while syncing to the database in the background sounds great in theory, but creates hard-to-debug consistency issues. We learned to reload from the database as the source of truth.

  • MongoDB's upsert is powerful. Using updateOne with upsert: true and a compound filter (userId + companyId) eliminated duplicate record bugs entirely.

  • Seed data matters. Having realistic demo data with complete user profiles, properly linked events and companies, and sensible defaults made testing and demoing dramatically easier.

  • ID generation belongs on the server. Generating IDs on both the client and server led to mismatches. A single source of truth for identity eliminated an entire class of bugs.

What's next for PitchPrep

  • Progressive Web App (PWA) — Make it installable on phones so students can reference their pitches while walking the career fair floor
  • Multi-user score isolation — Store match scores per-user in the Pitches collection instead of on the Company document, so different students see different scores for the same company
  • Resume intelligence — Use AI to parse resume bullet points and auto-extract skills, improving match accuracy without manual profile entry
  • Company comparison — Side-by-side view to help students choose between similar employers
  • Analytics dashboard — Show career services which companies students are most interested in, helping them curate better events
  • Calendar integration — Sync career fair dates to Google Calendar / Apple Calendar with reminders
  • Recruiter mode — Let employers log in, see which students are interested, and reach out proactively

Built With

Share this project:

Updates