Skip to main content

CV Unified WebSocket Service

Overview

This document describes the unified WebSocket-based CV processing service that consolidates all CV upload, parsing, and extraction functionality into a single, consistent API.

Architecture

Core Components

  1. useCvProcessor Hook - Unified hook for all CV processing needs
  2. ConnectionStatus Component - Reusable WebSocket connection indicator
  3. ProcessingIndicator Component - Reusable progress and status display

Migration from Old Hooks

The following hooks are deprecated but still available:

  • ⚠️ useCvUploadAndParse (GraphQL-based) — deprecated, use useCvProcessor for new code
  • ⚠️ useCvManager (GraphQL-based) — deprecated, use useCvProcessor for new code
  • useCvExtraction (WebSocket-based, limited functionality)
  • useCvProcessor (New unified WebSocket-based hook)

Hook API

useCvProcessor

import { useCvProcessor } from "@hooks/useCvProcessor"

const {
// Core function
processFile,

// Status
isConnected,
processing,
result,

// Actions
resetState,
clearError,
} = useCvProcessor()

Core Function

processFile(file: File, options?: CvProcessingOptions): Promise<CvData | null>

Uploads a file and processes it using WebSocket-based CV extraction.

Options:

  • companyId?: string - Company context for processing
  • persistent?: boolean - false = temporary extraction, true = stored processing

Status Properties

isConnected: boolean - WebSocket connection status

processing: CvProcessingStatus

{
isUploading: boolean
isProcessing: boolean
uploadProgress: number | null
status: string | null
error: string | null
}

result: CvData | null - Extracted CV data

interface CvData {
firstName?: string
lastName?: string
email?: string
portfolioLink?: string
linkedinLink?: string
description?: string
skills?: Array<{
name: string
proficiency?: string
yearsExperience?: number
}>
experiences?: Array<{
jobTitle?: string
company?: string
startDate?: string
endDate?: string
experience?: string
}>
education?: Array<{
title?: string
institute?: string
startDate?: string
endDate?: string
}>
fileUrl?: string
}

Reusable Components

ConnectionStatus

import { ConnectionStatus } from "@components/cv/ConnectionStatus"
;<ConnectionStatus isConnected={isConnected} className="mb-4" />

Shows real-time WebSocket connection status with appropriate styling.

ProcessingIndicator

import { ProcessingIndicator } from "@components/cv/ProcessingIndicator"
;<ProcessingIndicator
processing={processing}
fileName={file?.name}
className="mt-4"
/>

Displays upload progress, processing status, and loading indicators.

Usage Examples

Basic CV Processing

import { useCvProcessor } from "@hooks/useCvProcessor"
import { ConnectionStatus } from "@components/cv/ConnectionStatus"
import { ProcessingIndicator } from "@components/cv/ProcessingIndicator"

function CVUploadForm() {
const [file, setFile] = useState<File | null>(null)
const { processFile, isConnected, processing, result, clearError } =
useCvProcessor()

const handleUpload = async () => {
if (!file) return

const cvData = await processFile(file, { persistent: false })

if (cvData) {
// Handle extracted data
console.log("CV processed:", cvData)
}
}

return (
<div>
<ConnectionStatus isConnected={isConnected} />

<input
type="file"
accept=".pdf,.doc,.docx"
onChange={(e) => setFile(e.target.files?.[0] || null)}
/>

<Button
onClick={handleUpload}
disabled={
!file ||
!isConnected ||
processing.isUploading ||
processing.isProcessing
}
isLoading={processing.isUploading || processing.isProcessing}
>
Process CV
</Button>

<ProcessingIndicator processing={processing} fileName={file?.name} />

{processing.error && (
<div className="error">
{processing.error}
<Button onClick={clearError}>Dismiss</Button>
</div>
)}

{result && <div>CV processed successfully!</div>}
</div>
)
}

Company Candidate Processing

const handleCandidateCV = async (file: File) => {
const cvData = await processFile(file, {
companyId: user?.selectedCompanyId,
persistent: true, // Store permanently for candidate
})

if (cvData) {
// Auto-fill candidate form
setFormData({
firstName: cvData.firstName,
lastName: cvData.lastName,
email: cvData.email,
// ... other fields
})
}
}

Job Seeker Onboarding

const handleOnboardingCV = async (file: File) => {
const cvData = await processFile(file, {
persistent: false, // Temporary extraction for profile setup
})

if (cvData) {
// Auto-fill onboarding profile
setProfileData(cvData)
proceedToNextStep()
}
}

Migration Guide

From useCvUploadAndParse

Before:

const { uploadAndParse, isUploading, isParsing, error } = useCvUploadAndParse()

const parsedData = await uploadAndParse(file, companyId)

After:

const { processFile, processing, clearError } = useCvProcessor()

const parsedData = await processFile(file, { companyId, persistent: false })

From useCvExtraction

Before:

const { extractFromFile, isUploading, isProcessing, result } = useCvExtraction()

const data = await extractFromFile(file)

After:

const { processFile, processing, result } = useCvProcessor()

const data = await processFile(file, { persistent: false })

File Support

Supported formats:

  • PDF (.pdf)
  • Microsoft Word (.doc, .docx)
  • Plain text (.txt)

Maximum file size: 50MB

Error Handling

The hook provides comprehensive error handling:

  1. File validation - Type and size checks
  2. Connection errors - WebSocket connectivity issues
  3. Upload errors - Network or server issues during upload
  4. Processing errors - AI extraction failures

Errors are automatically displayed via toast notifications and available in processing.error.

WebSocket Events

The service uses the following WebSocket events:

  • cv_extraction - Temporary processing (not stored)
  • cv_processing - Persistent processing (stored in system)

Performance

  • Upload Progress - Real-time progress tracking
  • Processing Status - Live updates during AI extraction
  • Connection Management - Automatic reconnection handling
  • Error Recovery - Graceful error handling with retry options

Testing

Use the CV demo page for testing:

/app/(shared)/cv-demo/page.tsx

Or the CVExtractor component:

import { CVExtractor } from "@components/cv/CVExtractor"
;<CVExtractor />

Best Practices

  1. Always check connection status before processing
  2. Use appropriate persistence setting based on use case
  3. Handle errors gracefully with user-friendly messages
  4. Show progress indicators for better UX
  5. Validate files before processing (type, size)

Configuration

The WebSocket URLs are hardcoded in the application for production readiness:

  • Production: wss://pipeline.aiqlick.com
  • Development: ws://localhost:8000

No environment variables are required for pipeline connectivity. The system automatically selects the appropriate URL based on the deployment context.

Note: Make sure your local pipeline service is running on port 8000 for development testing. If the service is unavailable, the system will show appropriate error messages and stop reconnection attempts after 5 tries.