consolecv.opscores.in
ConsoleCV

ConsoleCV

A SaaS that reads unstructured resume PDFs with Llama 3 and rebuilds them properly - editor, PDF export, public portfolio page included.

Timeline
2024
Role
Solo build
Team
Solo
Status
live

Technology Stack

Next.js 14Next.js 14TypeScriptTypeScriptGroq SDKLlama 3Llama 3NextAuth v5MongoDBMongoDBUpstash RedisUpstash Redis@react-pdf/renderer

Overview

ConsoleCV is an AI-powered resume builder SaaS where every PDF upload enters a pipeline: Llama 3 via the Groq SDK parses the unstructured content, extracts structured fields (education, experience, skills), and hands it to a live editor - so a resume locked in a PDF becomes an editable document in seconds.

It is built as a proper SaaS: gated flows behind NextAuth v5 sessions, Upstash Redis rate limiting on expensive AI endpoints, and an AuditLog model that records every unauthorized request with severity levels. Resume data is personal - audit trails, rate limits and access controls are non-negotiable, not an afterthought.

Key Features

  • Llama 3 AI parsing via Groq - Unstructured resume PDFs are fed to Llama 3 through the Groq SDK - sub-second inference on Groq's custom chips - and the output maps to a structured Resume Zod schema ready for editing.

  • Resume editor + PDF export - Parsed data drops into a live editor. @react-pdf/renderer generates a professional layout client-side on demand - no server round-trip, no layout drift between editor view and download.

  • NextAuth v5 + Redis rate limiting - Sessions are handled by NextAuth v5 (Edge Runtime compatible). AI endpoints are rate-limited per authenticated user ID via Upstash Redis - cost spikes from a single account are blocked before they reach the Groq API.

  • AuditLog - unauthorized access is observable - Every unauthenticated request to a protected endpoint is logged to MongoDB with IP address, user agent, endpoint, method and severity level. Abuse patterns surface before they compound.

  • Public portfolio page - Parsed and edited resumes can be published as a public page at /[username] - shareable with recruiters directly, a second deliverable that makes ConsoleCV more than a PDF generator.

Technical Implementation

01Audit logging - every unauthorized request recorded

The resume API logs every unauthorized access attempt before returning 401. Audit trails are a compliance pattern more common in fintech than resume builders - applied here because the data is personal and the attack surface (public SaaS) demands it.

app/api/resume/route.ts
ts
// Every unauthenticated request is logged with severity HIGH
if (!session?.user?.id) {
  await AuditLog.log("UNAUTHORIZED_ACCESS", {
    ipAddress: getClientIp(request),
    userAgent: request.headers.get("user-agent") ?? "Unknown",
    details: { endpoint: "/api/resume", method: request.method },
    severity: "HIGH",
  });
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

// Rate-limited per authenticated user (not just IP)
const rl = await rateLimitAuthenticated(session.user.id);
if (!rl.success)
  return rateLimitExceededResponse(createRateLimitHeaders(rl));

02Groq + Llama 3 parsing pipeline

PDFs are converted to plain text, sent to Llama 3 through the Groq SDK with a structured extraction prompt, and the output is validated against a Zod schema before being written to MongoDB. The prompt includes explicit negative instructions ('if the field is not present, return null - never invent') to prevent the model hallucinating missing experience or skills.

03Data model

Three Mongoose models: Resume (structured schema matching the editor fields), User (NextAuth-integrated, hashed passwords), and AuditLog (time-series append-only - severity indexed for alerting). Resume ownership is enforced at the query level - every resume endpoint filters by session.user.id.

ModelKey fieldsPurpose
ResumeuserId, sections[], parsedAt, publishedAtThe parsed + edited resume document
Useremail, hashedPassword, usernameAuth identity, links to public /[username] page
AuditLogevent, userId?, ipAddress, severity, timestampAppend-only access trail for monitoring

Project Structure

structure
consolecv/
├─ src/
│  ├─ app/
│  │  ├─ (auth)/      # login, register
│  │  ├─ dashboard/   # user dashboard
│  │  ├─ editor/      # resume editor
│  │  ├─ [username]/  # public portfolio page
│  │  └─ api/         # AI parsing, resume CRUD, user endpoints
│  ├─ models/         # Resume, User, AuditLog
│  ├─ auth.ts         # NextAuth v5 config
│  └─ middleware.ts   # route protection
└─ public/            # static assets

Design Decisions

Groq over OpenAI for speed

The parsing step needs to feel instant - a multi-second spinner kills the moment when the resume appears structured. Groq's custom inference chips serve Llama 3 faster than OpenAI's API at this price point. The difference is perceptible in the UX.

AuditLog as a first-class model

Resume data is personal. An observable audit trail means suspicious access patterns - mass enumeration, repeated 401s from the same IP - surface without log-scraping. The AuditLog model is append-only and severity-indexed so a simple query identifies incidents.

Challenges

PDF extraction loses layout context

PDF → plain text loses the formatting cues that matter for resume parsing: columns become garbled runs of text, tables collapse, header hierarchy disappears. Mitigated by a parsing prompt that targets semantic structure (section names, date ranges, bullet patterns) rather than visual layout.

Model hallucinations on sparse resumes

Llama 3 sometimes extrapolates missing fields - dates, employer names - when the PDF is thin. Fixed with explicit negative instructions in the system prompt ('never invent data') and post-parse Zod validation that rejects any field value not derivable from the source text.

Want the full walkthrough - architecture, decisions, war stories?

ask me about it