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.

getAiResponse is the core AI integration layer in Resume Check Karo. It receives a browser File object and a pre-built instruction prompt, base64-encodes the PDF, submits both to Google Gemini as a single multimodal user turn, and parses the model’s structured JSON response into a typed Feedback object. All AI-layer errors are caught internally so callers always receive a valid data shape.

Signature

export async function getAiResponse(file: File, instruction: string): Promise<Feedback>

Parameters

file
File
required
The resume PDF to analyze. Internally, the function reads the file as an ArrayBuffer, converts it to a Node.js Buffer, and encodes it as a Base64 string before including it as an inlineData part in the Gemini request. The MIME type is hardcoded to "application/pdf".
instruction
string
required
The full text prompt that directs the model’s analysis. In normal usage this is built by prepareInstructions inside the analyzeResume server action — it includes the target company name, job title, full job description, and the five evaluation criteria the model must score.

Return Type

Returns Promise<Feedback> — a fully structured analysis result parsed from the model’s JSON output.
See the Feedback Types reference for the complete Feedback, FeedbackSection, and FeedbackTip interface definitions.

Implementation Details

The resumeAnalysisSchema Object

The schema enforces the exact shape of the model’s JSON output. The ATS section requires only type and tip on each tip item. All other sections (toneAndStyle, content, structure, skills) additionally require an explanation field on each tip.
export const resumeAnalysisSchema = {
  type: Type.OBJECT,
  properties: {
    overallScore: { type: Type.NUMBER },
    ATS: {
      type: Type.OBJECT,
      properties: {
        score: { type: Type.NUMBER },
        tips: {
          type: Type.ARRAY,
          items: {
            type: Type.OBJECT,
            properties: {
              type: { type: Type.STRING, enum: ["good", "improve"] },
              tip: { type: Type.STRING },
              // No "explanation" property — omitted for ATS by design
            },
            required: ["type", "tip"],
          },
        },
      },
      required: ["score", "tips"],
    },
    toneAndStyle: {
      type: Type.OBJECT,
      properties: {
        score: { type: Type.NUMBER },
        tips: {
          type: Type.ARRAY,
          items: {
            type: Type.OBJECT,
            properties: {
              type: { type: Type.STRING, enum: ["good", "improve"] },
              tip: { type: Type.STRING },
              explanation: { type: Type.STRING },
            },
            required: ["type", "tip", "explanation"], // explanation is required for non-ATS sections
          },
        },
      },
      required: ["score", "tips"],
    },
    // content, structure, and skills follow the same shape as toneAndStyle
  },
  required: ["overallScore", "ATS", "toneAndStyle", "content", "structure", "skills"],
};

Error Handling

If any step in the pipeline fails — the API call throws, response.text is empty, or JSON.parse raises a SyntaxError — the catch block logs a structured diagnostic object and returns createErrorFeedback() instead of propagating the exception.
// Logged to console on failure:
{
  error: err instanceof Error ? err.message : err,
  jsonOutput,   // Raw text that failed to parse (if applicable)
  fileName: file.name,
  fileSize: file.size,
}
The fallback object returned to the caller looks like this:
{
  overallScore: 0,
  ATS:          { score: 0, tips: [{ type: "improve", tip: "Analysis failed: internal server error" }] },
  toneAndStyle: { score: 0, tips: [{ type: "improve", tip: "Unable to analyze" }] },
  content:      { score: 0, tips: [{ type: "improve", tip: "Unable to analyze" }] },
  structure:    { score: 0, tips: [{ type: "improve", tip: "Unable to analyze" }] },
  skills:       { score: 0, tips: [{ type: "improve", tip: "Unable to analyze" }] },
}
Because getAiResponse never re-throws AI errors, the analyzeResume server action will always receive a valid Feedback object. Zero scores across all sections are the signal that the AI call failed at runtime.
The model name is accessed with a TypeScript non-null assertion (process.env.GOOGLE_AI_MODEL!). If this environment variable is missing or misspelled at runtime, the Gemini SDK will throw immediately and the error fallback will be returned. Always verify GOOGLE_AI_MODEL is set in your .env.local (development) and your deployment environment before going live.

Build docs developers (and LLMs) love