Skip to content

feat(batch): add batch upload for resume analysis against multiple jobs - #28

Open
prathamdby wants to merge 2 commits into
masterfrom
tembo/batch-upload-resume-multi-jobs
Open

prathamdby wants to merge 2 commits into
masterfrom
tembo/batch-upload-resume-multi-jobs

Conversation

@prathamdby

@prathamdby prathamdby commented Jul 24, 2026

Copy link
Copy Markdown
Owner

PR Agent Description

PR Type

Enhancement

Description

  • Add batch resume analysis: upload one resume PDF and compare against 2–10 job descriptions in parallel
  • New NDJSON streaming API with semaphore-based concurrency (3 parallel AI calls per batch)
  • Extracted shared PDF conversion and AI analysis logic into reusable lib module
  • Real-time progress UI with live score cards and batch results summary page

File Walkthrough

Enhancement (10 files)
Batch analyze API route

app/api/batch-analyze/route.ts

  • New POST endpoint accepting resume PDF + job entries
  • Streams NDJSON progress events with semaphore-limited concurrency
  • Creates BatchAnalysis record and individual Resume entries
Batch upload form with live progress

app/components/BatchUploadForm.tsx

  • Step 1: resume PDF upload with validation
  • Step 2: add 2–10 job entries with title, company, description
  • Real-time streaming progress with per-job score cards
Batch results page with score summary

app/(dashboard)/app/batch/[id]/page.tsx

  • Summary stats: total jobs, completed, failed, avg score, best match
  • Grid of ResumeCard components linking to individual analyses
  • Handles completed, partial, and failed batch statuses
New BatchAnalysis database model

prisma/schema.prisma

  • BatchAnalysis model with status tracking (processing/completed/partial/failed)
  • Resume gains optional batchId relation with cascade set-null
Extracted shared resume analysis utilities

lib/resume-analysis.ts

  • convertPdfToMarkdown reused for batch and single analysis
  • analyzeResumeWithAI wraps AI request with system prompt
Client-side streaming API function

lib/api.ts

  • batchAnalyze() posts FormData and reads NDJSON stream
  • Parses progressive events via callback pattern
Batch input validation schemas

lib/schemas.ts

  • BatchJobEntrySchema: 2–10 jobs with validation
  • BatchAnalyzeInputSchema wraps job array
New batch analysis TypeScript types

types/index.d.ts

  • BatchAnalysis, BatchJobEntry, BatchStreamEvent types
  • Stream event union covers init/progress/complete phases
Rate limit for batch endpoint

lib/rate-limit.ts

  • 1 request per 120-second window
  • Prevents excessive batch submissions
Navigation links for batch feature

app/components/AppSidebar.tsx

  • Sidebar: new Batch Analyze nav item with Layers icon
  • Navbar: new Batch tab pill linking to batch-upload

@zeus-review

zeus-review Bot commented Jul 24, 2026

Copy link
Copy Markdown

PR Agent Review

Note

This PR adds a batch resume analysis feature allowing users to upload one resume and analyze it against 2-10 job descriptions in parallel. It introduces a new NDJSON streaming API endpoint (/api/batch-analyze) with custom concurrency control (Semaphore class limiting to 3 parallel AI calls), a new BatchAnalysis database model to track batch status, two new pages (upload form with real-time progress tracking and results dashboard with score comparisons), refactored shared PDF/AI logic into lib/resume-analysis.ts, rate limiting configuration (1 request per 120 seconds), and UI integration in sidebar and navbar. The implementation spans multiple layers: API routes with streaming responses, database schema changes with new relationships, complex client components managing streaming state, and server components with auth/ownership validation.

EffortSubstantial · 4/5
FindingsNo issues on this pass.
Relevant testsno
SecurityNo security vulnerabilities were identified by the security specialist. The batch results page includes proper ownership validation (`batch.userId !== session.user.id`) preventing cross-user access. Rate limiting is configured appropriately for the batch endpoint. File size and type validation are in place.
CI✅ All CI is passing
Follow-upsCorrectness specialist timed out during review - manually verify Semaphore concurrency control, NDJSON stream parsing error handling, and batch status transition logic before merge
Follow-upsRepository has no test suite (AGENTS.md explicitly states 'No additional test suites exist') - this PR introduces complex concurrent logic that would benefit from test coverage, particularly for error paths and edge cases
Follow-upsVerify streaming response behavior under error conditions: malformed NDJSON data, client disconnects mid-stream, and AI API timeouts to ensure graceful degradation and prevent resource waste

Coverage partial: correctness specialist failed.

5ddbde0 ⋅ general ⋅ 17m 49s ⋅ qwen3.7-plus

@@ -0,0 +1,20 @@
import BatchUploadForm from "@/app/components/BatchUploadForm";

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ask What's the purpose of this component?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page component (app/(dashboard)/app/batch-upload/page.tsx) is a batch resume analysis page that lets a user upload a single resume and compare it against up to 10 different job descriptions in parallel.

It renders two things:

  1. A header with the copy "One resume, multiple jobs. Analyzed in parallel." and a short description explaining the feature.
  2. <BatchUploadForm />, which is the real workhorse. That form handles:
    • Uploading one resume PDF.
    • Adding 2 to 10 job entries (title, company, description), each with an option to import details from a URL or a PDF.
    • Validating the form (each job needs a title and a description of at least 50 characters).
    • Calling batchAnalyze with streaming progress events, then rendering a live progress UI showing each job's status (analyzing, success with score, or error).
    • Once complete, offering a "View all results" button that navigates to /app/batch/{batchId}, plus per-job "View analysis" links to /app/resume/{resumeId}.

So the page itself is just a thin layout wrapper; the bulk of the logic lives in app/components/BatchUploadForm.tsx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant