Skip to main content

Overview

InterviewGuide leverages modern Java and TypeScript ecosystems with carefully selected libraries optimized for AI-powered applications.

Backend Stack

Core Framework

Latest major version with enhanced modularitySpring Boot 4.0 introduces significant improvements:
  • Java 21 LTS baseline: Virtual threads, pattern matching, records
  • Modular starters: Fine-grained dependency control
  • Native compilation: GraalVM native image support
  • Observability: Built-in metrics and tracing
// From build.gradle
plugins {
    id 'org.springframework.boot' version '4.0.1'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webmvc'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
Key Configuration (app/src/main/resources/application.yml):
spring:
  application:
    name: interview-guide
  
  datasource:
    url: jdbc:postgresql://localhost:5432/interview_guide
    username: postgres
    password: ${POSTGRES_PASSWORD}
    driver-class-name: org.postgresql.Driver
  
  jpa:
    hibernate:
      ddl-auto: update  # create for first run, then update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect

AI Integration

Spring AI 2.0.0-M1 provides a unified abstraction over multiple LLM providers, allowing easy switching between OpenAI, Azure OpenAI, AWS Bedrock, and Alibaba DashScope.
// Spring AI dependencies
implementation "org.springframework.ai:spring-ai-starter-model-openai:2.0.0-M1"
implementation "org.springframework.ai:spring-ai-starter-vector-store-pgvector:2.0.0-M1"
Why Spring AI?

Unified API

Single interface for multiple LLM providers:
  • OpenAI GPT-4
  • Azure OpenAI
  • Alibaba Qwen (DashScope)
  • AWS Bedrock
Switch providers with configuration, no code changes.

Vector Store Integration

Native support for vector databases:
  • pgvector (PostgreSQL)
  • Pinecone
  • Chroma
  • Weaviate
Automatic embedding and similarity search.

Structured Output

Type-safe response parsing:
@JsonClassDescription("Resume analysis")
record ResumeAnalysis(
    @JsonProperty(required = true) 
    int overallScore,
    
    @JsonProperty(required = true)
    List<String> skills
) {}

// Spring AI handles JSON schema generation
ResumeAnalysis result = chatClient.call(
    prompt, ResumeAnalysis.class
);

Streaming Support

Server-Sent Events (SSE) for real-time responses:
Flux<String> stream = chatClient
    .stream(prompt)
    .map(ChatResponse::getContent);

return SseEmitter.event()
    .data(stream);
Configuration (application.yml):
spring:
  ai:
    openai:
      # OpenAI-compatible API (Alibaba DashScope)
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: ${AI_BAILIAN_API_KEY}
      chat:
        options:
          model: ${AI_MODEL:qwen-plus}
          temperature: 0.7
    
    vectorstore:
      pgvector:
        initialize-schema: true  # Auto-create vector_store table
        index-type: HNSW         # Hierarchical Navigable Small World
        distance-type: COSINE_DISTANCE
        dimensions: 1536         # OpenAI embedding dimension

Database Layer

Production-grade relational database with vector extensionPostgreSQL selected for:
  • ACID compliance: Reliable transactions
  • Rich data types: JSONB, arrays, full-text search
  • pgvector extension: Native vector storage and similarity search
  • Mature ecosystem: Excellent tooling and community support
Schema Initialization:
-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Spring AI auto-creates this table
CREATE TABLE vector_store (
    id UUID PRIMARY KEY,
    content TEXT,
    metadata JSONB,
    embedding vector(1536)  -- OpenAI embedding size
);

-- HNSW index for fast similarity search
CREATE INDEX ON vector_store 
USING hnsw (embedding vector_cosine_ops);

Redis Layer

Redisson 4.0.0 - Advanced Redis Java client with Spring Boot 4.0 compatibility
implementation "org.redisson:redisson-spring-boot-starter:4.0.0"
Dual Purpose Architecture:
Session cache for interview state
spring:
  redis:
    redisson:
      config: |
        singleServerConfig:
          address: "redis://localhost:6379"
          database: 0
          connectionPoolSize: 64
          connectionMinimumIdleSize: 10
@Service
public class InterviewSessionCache {
    private final RedisService redisService;
    private static final Duration SESSION_TTL = Duration.ofHours(2);
    
    public void cacheSession(String sessionId, InterviewSession session) {
        String key = "interview:session:" + sessionId;
        redisService.set(key, session, SESSION_TTL);
    }
    
    public InterviewSession getSession(String sessionId) {
        String key = "interview:session:" + sessionId;
        return redisService.get(key);
    }
}
Why Redis cache over ConcurrentHashMap?
  • Shared state: Multiple backend instances can access same cache
  • TTL management: Automatic expiration of old sessions
  • Persistence: Survives application restarts
  • Memory limits: Eviction policies prevent OOM

Document Processing

Universal document parser
implementation 'org.apache.tika:tika-core:2.9.2'
implementation 'org.apache.tika:tika-parsers-standard-package:2.9.2'
Tika handles multiple formats:
  • PDF: Using Apache PDFBox
  • Microsoft Office: DOCX, DOC, XLSX, PPTX
  • OpenOffice: ODT, ODS, ODP
  • Plain text: TXT, CSV, Markdown
  • HTML/XML: Web documents
@Service
public class FileParsingService {
    private final AutoDetectParser parser = new AutoDetectParser();
    
    public String extractText(InputStream input) throws Exception {
        BodyContentHandler handler = new BodyContentHandler(-1);  // No limit
        Metadata metadata = new Metadata();
        ParseContext context = new ParseContext();
        
        parser.parse(input, handler, metadata, context);
        return handler.toString();
    }
}
Supported Resume Formats:
  • PDF (most common)
  • DOCX (Microsoft Word 2007+)
  • DOC (legacy Word)
  • TXT (plain text)

Utilities

MapStruct 1.6.3

Compile-time object mapping
implementation "org.mapstruct:mapstruct:1.6.3"
annotationProcessor "org.mapstruct:mapstruct-processor:1.6.3"
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
@Mapper(componentModel = "spring")
public interface ResumeMapper {
    ResumeDTO toDTO(ResumeEntity entity);
    
    @Mapping(target = "id", ignore = true)
    ResumeEntity toEntity(ResumeCreateRequest request);
}
Why MapStruct over manual mapping?
  • Type-safe at compile time
  • Zero reflection overhead
  • Auto-generated code visible in IDE
  • Lombok integration

Lombok 1.18.36

Boilerplate reduction
compileOnly 'org.projectlombok:lombok:1.18.36'
annotationProcessor 'org.projectlombok:lombok:1.18.36'
@Slf4j  // Auto-generates logger
@Service
@RequiredArgsConstructor  // Constructor for final fields
public class ResumeService {
    private final ResumeRepository repository;
    private final FileParsingService fileParser;
    
    public void processResume(MultipartFile file) {
        log.info("Processing resume: {}", file.getOriginalFilename());
        // ...
    }
}

Storage

S3-compatible object storage
implementation "software.amazon.awssdk:s3:2.29.51"
app:
  storage:
    endpoint: http://localhost:9000      # RustFS or MinIO
    access-key: ${APP_STORAGE_ACCESS_KEY}
    secret-key: ${APP_STORAGE_SECRET_KEY}
    bucket: interview-guide
    region: us-east-1
@Service
public class S3StorageService {
    private final S3Client s3Client;
    
    public String uploadFile(String key, InputStream input, long size) {
        PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(key)
            .contentLength(size)
            .build();
        
        s3Client.putObject(request, RequestBody.fromInputStream(input, size));
        return generatePublicUrl(key);
    }
}
Supported storage backends:
  • RustFS: Lightweight S3-compatible server (Docker deployment)
  • MinIO: Self-hosted S3-compatible storage
  • AWS S3: Production cloud storage
  • Alibaba OSS: China region deployment

Frontend Stack

Core Framework

// frontend/package.json
{
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.11.0",
    "typescript": "~5.6.2",
    "vite": "^5.4.10"
  }
}
Modern UI library with concurrent features
  • Concurrent rendering: Automatic batching, transitions
  • Suspense: Declarative loading states
  • Server Components: Future-ready architecture
  • Hooks: Functional component patterns

UI Libraries

Tailwind CSS 4.1

Utility-first CSS framework
"@tailwindcss/postcss": "^4.1.18",
"@tailwindcss/typography": "^0.5.15"
<div className="max-w-4xl mx-auto p-6 bg-white rounded-lg shadow-md">
  <h1 className="text-2xl font-bold text-gray-800 mb-4">
    Resume Analysis
  </h1>
</div>

Framer Motion 12.23

Declarative animations
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.3 }}
>
  {/* Content */}
</motion.div>

Recharts 3.6

React charting library
<RadarChart data={skillsData}>
  <PolarGrid />
  <PolarAngleAxis dataKey="skill" />
  <Radar dataKey="score" fill="#8884d8" />
</RadarChart>

Lucide React 0.468

Beautiful icon library
import { FileText, Upload, Download } from 'lucide-react';

<Upload className="w-5 h-5" />

Advanced Features

Markdown rendering with syntax highlighting
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^16.1.0",
"remark-gfm": "^4.0.0",
"remark-breaks": "^4.0.0"
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';

<ReactMarkdown
  remarkPlugins={[remarkGfm, remarkBreaks]}
  components={{
    code({node, inline, className, children, ...props}) {
      const match = /language-(\w+)/.exec(className || '');
      return !inline && match ? (
        <SyntaxHighlighter language={match[1]} PreTag="div">
          {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
      ) : (
        <code className={className} {...props}>
          {children}
        </code>
      );
    }
  }}
>
  {content}
</ReactMarkdown>

Version Matrix

Backend Dependencies

ComponentVersionRelease DateSupport Until
Java21 LTSSep 2023Sep 2031 (8 years)
Spring Boot4.0.1Nov 2024Nov 2026
Spring AI2.0.0-M1MilestoneTBD
PostgreSQL14+Sep 2021Nov 2026
Redis6+May 2020Active
Redisson4.0.02024Active
Apache Tika2.9.2Sep 2023Active
iText8.0.52024Commercial
MapStruct1.6.32024Active
Lombok1.18.362024Active

Frontend Dependencies

ComponentVersionRelease DateLTS Status
React18.3.1Apr 2024Stable
TypeScript5.6.2Sep 2024Stable
Vite5.4.10Oct 2024Stable
Tailwind CSS4.1.18Jan 2025Stable
React Router7.11.0Jan 2025Stable
Framer Motion12.23.26Jan 2025Stable

Next Steps

Architecture Overview

Understand the overall system design and component interactions

Async Processing

Deep dive into Redis Streams implementation patterns

Build docs developers (and LLMs) love