Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nayalsaurav/resume-analyzer/llms.txt

Use this file to discover all available pages before exploring further.

analyzeResume is a Next.js server action ("use server") that orchestrates the full resume analysis pipeline. It validates all inputs, constructs a detailed ATS-focused prompt via prepareInstructions, delegates the AI call to getAiResponse, and returns a structured Feedback object ready for display.

Signature

export const analyzeResume = async ({
  companyName,
  jobTitle,
  jobDescription,
  file,
}: AnalyzeResumeProps): Promise<Feedback>

Parameters

companyName
string
required
Name of the target company the applicant is applying to. Used as context in the AI prompt so the model can tailor ATS keyword recommendations to the specific employer.
jobTitle
string
required
The exact position title being applied for (e.g. "Senior Frontend Engineer"). Passed directly into the analysis prompt to align scoring with role-specific expectations.
jobDescription
string
required
Full text of the job description copied from the posting. The AI compares resume content against this text for keyword matching, relevance scoring, and ATS compatibility.
file
File
required
The applicant’s resume as a browser File object. Must be a PDF (application/pdf) and no larger than 10 MB. The file is base64-encoded before being sent to the Gemini model.

Return Type

Returns Promise<Feedback> — the complete AI analysis result containing an overall score and five scored sections, each with 3–4 actionable tips.
See the Feedback Types reference for the full interface definitions of Feedback, FeedbackSection, and FeedbackTip.

Validation

Before the AI call is made, validateInputs checks every field and collects all failures into a single error. If any rule is violated, the action throws immediately and the AI is never contacted.
RuleCondition
companyName is requiredMust not be empty or whitespace-only
jobTitle is requiredMust not be empty or whitespace-only
jobDescription is requiredMust not be empty or whitespace-only
file is requiredMust be a non-null File object
file.type must be PDFfile.type === "application/pdf"
file.size must be ≤ 10 MBfile.size <= 10 × 1024 × 1024 bytes
When one or more rules fail, validateInputs throws:
Error: "Validation failed: <comma-separated list of messages>"
For example, submitting an empty company name and a non-PDF file produces:
Error: "Validation failed: Company name is required, Only PDF files are supported"

Error Handling

Validation errors are re-thrown to the caller — your form or API route is responsible for catching them and surfacing the message to the user.
Errors raised during the AI call (network failures, empty model responses, JSON parse errors) are handled entirely inside getAiResponse. That function catches all AI-layer exceptions and returns a zero-score fallback Feedback object so the UI always receives a valid data shape rather than an unhandled rejection.
analyzeResume caller
  └─ validateInputs()       ← throws Error on failure (re-thrown to caller)
  └─ getAiResponse()        ← catches AI errors internally, returns fallback Feedback

Usage Example

The example below shows how to call analyzeResume from a client component’s form submit handler using React state for loading and error feedback.
"use client";

import { useState } from "react";
import { analyzeResume } from "@/app/actions/analyze-resume";
import type { Feedback } from "@/lib/google";

export default function ResumeForm() {
  const [feedback, setFeedback] = useState<Feedback | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setError(null);
    setLoading(true);

    const form = e.currentTarget;
    const data = new FormData(form);

    const file = data.get("resume") as File;
    const companyName = data.get("companyName") as string;
    const jobTitle = data.get("jobTitle") as string;
    const jobDescription = data.get("jobDescription") as string;

    try {
      const result = await analyzeResume({
        companyName,
        jobTitle,
        jobDescription,
        file,
      });
      setFeedback(result);
    } catch (err) {
      // Validation errors are thrown here; AI errors return a fallback Feedback
      setError(err instanceof Error ? err.message : "An unexpected error occurred");
    } finally {
      setLoading(false);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="companyName" placeholder="Company name" required />
      <input name="jobTitle" placeholder="Job title" required />
      <textarea name="jobDescription" placeholder="Paste job description…" required />
      <input name="resume" type="file" accept="application/pdf" required />
      <button type="submit" disabled={loading}>
        {loading ? "Analyzing…" : "Analyze Resume"}
      </button>
      {error && <p style={{ color: "red" }}>{error}</p>}
      {feedback && <pre>{JSON.stringify(feedback, null, 2)}</pre>}
    </form>
  );
}
analyzeResume is a server action. While it can be invoked from both client and server components, it must be called via Next.js’s server action mechanism — not treated as a plain async function in browser-only contexts such as useEffect. Ensure the importing module either has "use client" or "use server" at the top as appropriate.

Build docs developers (and LLMs) love