Back to Projects
Developer ToolsFeatured

CovGen – LLM-Powered Cover Letter Generator

A production-quality Python CLI tool that revolutionizes the cover letter writing process through intelligent automation. CovGen fetches job descriptions from URLs or local files, intelligently extracts company and contact information using sophisticated regex patterns and frequency analysis, combines this with your CV context, and generates personalized cover letter content via configurable LLM providers (OpenAI, Together.ai, OpenRouter). The generated content is then rendered through Jinja2-templated LaTeX and compiled into publication-quality PDFs. Features include smart paragraph splitting, LaTeX character escaping, job description snapshots for traceability, and extensive CLI customization options.

3 (OpenAI, Together, OpenRouter)

LLM Providers

PDF + LaTeX + Snapshot

Output Formats

Pydantic v2 + .env

Config System

Typer + Rich

CLI Framework

Tech Stack

13 technologies used

PythonTyperPydantic v2Jinja2OpenAI APITogether AIOpenRouterClaudeGPT-4Llama 3.1LaTeXXeTeXBeautifulSoup4

System Components

6 interconnected services

The architecture consists of these cooperating services, each with distinct responsibilities:

CLI Interface

frontend

Typer-powered command-line interface with rich terminal output. Supports the `generate` command with extensive flags for customization including role, company, tone, temperature, sender/recipient details, and output options.

TyperRichPython 3.10+

Pipeline Orchestrator

backend

Core orchestration module (480+ lines) coordinating the entire generation flow: job fetching, company extraction, CV loading, LLM generation, post-processing, template rendering, and PDF compilation.

PythonPydantic v2

LLM Abstraction Layer

backend

Unified multi-provider wrapper supporting OpenAI, Together.ai, and OpenRouter APIs. Handles provider-specific authentication, model selection, and response parsing with configurable temperature.

Protocol:REST/HTTPS
OpenAI SDKTogether APIOpenRouter API

Job Fetcher

backend

Intelligent job description loader supporting both URLs and local files. Uses BeautifulSoup for HTML parsing, extracts metadata, strips scripts/styles, and normalizes whitespace.

Protocol:HTTP/HTTPS
RequestsBeautifulSoup4lxml

LaTeX Renderer

backend

Jinja2-based template engine producing professional letter layouts. Features conditional recipient logic, custom opening/closing phrases, microtype polish, and XeTeX font support. Compiles to PDF via xelatex/pdflatex.

Jinja2LaTeXXeTeX

Configuration System

infrastructure

Pydantic v2 BaseSettings with custom lenient environment sources. Supports .env files, environment variables, JSON lists, and pipe-separated values. Validates API keys match selected provider.

Pydantic v2pydantic-settingspython-dotenv

Data Flow

10 steps from input to output

How data flows through the system from client request to final response:

1
UserCLI InterfaceTerminal

User invokes `covergen generate <url>` with optional flags

2
CLI InterfaceJob FetcherHTTP/File I/O

Fetches job description from URL or reads local file

3
Job FetcherPipeline OrchestratorInternal

Extracts company name, contact info using regex + frequency analysis

4
Pipeline OrchestratorCV LoaderFile I/O

Loads user's CV text from configured path

5
Pipeline OrchestratorLLM ProviderHTTPS

Sends structured prompt with CV + job context to selected LLM

6
LLM ProviderPipeline OrchestratorHTTPS

Returns generated cover letter body content

7
Pipeline OrchestratorPost-ProcessorInternal

Sanitizes output: removes duplicates, splits paragraphs, escapes LaTeX chars

8
Post-ProcessorLaTeX RendererInternal

Renders Jinja2 template with generated content and metadata

9
LaTeX RendererXeTeX CompilerSubprocess

Compiles .tex to .pdf using xelatex engine

10
Pipeline OrchestratorOutput DirectoryFile I/O

Saves .pdf, .tex source, and .job.txt snapshot

Code Examples

4 ready-to-use snippets

Get started quickly with these practical code examples:

BASH

Basic Generation

Generate a cover letter from a job posting URL

# Generate cover letter from a job posting URL
covergen generate "https://careers.example.com/job/12345"

# Output:
# ✓ Fetched job description (2,847 chars)
# ✓ Extracted company: Example Corp
# ✓ Generated letter via OpenAI (gpt-4-turbo)
# ✓ Compiled PDF: output/software-engineer-example-corp-2024-01-15.pdf
BASH

Advanced CLI Options

Full customization with role, tone, and recipient overrides

covergen generate ./job-posting.html \
  --role "Senior Backend Engineer" \
  --company "TechCorp" \
  --tone "enthusiastic yet professional" \
  --instructions "Emphasize distributed systems experience" \
  --sender-name "Sandeep Hirani" \
  --sender-address "123 Main St" \
  --sender-address "Ames, IA 50010" \
  --recipient-name "Jane Smith" \
  --recipient-company "TechCorp Engineering" \
  --output-stem "techcorp-backend-senior"
BASH

Environment Configuration

Sample .env file with multi-provider setup

# LLM Provider Configuration
LLM_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4-turbo

# Alternative providers (uncomment to use)
# LLM_PROVIDER=together
# TOGETHER_API_KEY=...
# TOGETHER_MODEL=meta-llama/Llama-3.1-70B-Instruct

# LLM_PROVIDER=openrouter
# OPENROUTER_API_KEY=...
# OPENROUTER_MODEL=anthropic/claude-3.5-sonnet

# Generation settings
LLM_TEMPERATURE=0.2
DEFAULT_TONE=professional and warm

# Sender defaults (pipe-separated for multi-line)
DEFAULT_SENDER_NAME=Sandeep Hirani
DEFAULT_SENDER_ADDRESS=123 Main St|Ames, IA 50010
TEXT

Prompt Engineering

System prompt ensuring grounded, professional output

You are an expert cover letter writer. Generate ONLY the body
paragraphs (2-3 paragraphs) for a cover letter.

CRITICAL CONSTRAINTS:
- Ground ALL claims in the provided CV - NO fabricated achievements
- Include quantified metrics from actual experience
- Match tone to job requirements (default: professional, warm)
- Avoid clichés like "I am writing to express my interest"
- Output valid LaTeX content (escape special characters)

CV CONTEXT:
{cv_text}

JOB DESCRIPTION:
{job_description}

Generate 2-3 focused paragraphs connecting CV experience to job needs.

Infrastructure

Production-ready deployment stack

Battle-tested infrastructure components for reliable operations:

Multi-Provider LLM Layer

gateway

Unified abstraction over OpenAI, Together.ai, and OpenRouter APIs. Per-provider model configuration with shared fallback. Handles authentication, rate limiting, and response normalization.

OpenAI SDKTogether APIOpenRouter APIhttpx

Configuration Management

storage

Pydantic v2 BaseSettings with custom lenient parsers for environment variables. Supports .env files, JSON lists, pipe-separated values, and path expansion. Validates provider-API key alignment.

Pydantic v2pydantic-settingspython-dotenv

Document Processing Pipeline

deployment

End-to-end document pipeline: HTML parsing with BeautifulSoup, Jinja2 template rendering, LaTeX compilation via xelatex subprocess, and artifact management (PDF, source, snapshots).

BeautifulSoup4Jinja2XeTeXsubprocess

CLI & Developer Experience

monitoring

Typer-powered CLI with Rich terminal formatting. Comprehensive help text, flag validation, and informative error messages. Package installable via pip with entry point.

TyperRichsetuptoolspip

Key Features

  • Multi-provider LLM architecture supporting OpenAI (GPT-4), Together.ai (Llama 3.1), and OpenRouter (Claude 3.5 Sonnet)
  • Intelligent company name extraction using regex patterns, frequency analysis, and 45+ stopword filtering
  • Smart contact/hiring manager detection from job posting metadata and content
  • Advanced prompt engineering with grounding constraints preventing fabricated achievements
  • Post-processing pipeline: duplicate removal, paragraph splitting, LaTeX character escaping
  • Jinja2-templated LaTeX with conditional logic for named contacts vs company-only recipients
  • Job description snapshots (.job.txt) archiving original postings for audit trails
  • Lenient environment configuration tolerating both JSON and pipe-separated list formats
  • Granular CLI overrides for role, company, tone, temperature, and sender/recipient details

Challenges Solved

  • Extracting structured company and contact data from highly variable job posting formats across different websites
  • Designing a unified abstraction layer across three LLM providers with different API interfaces and response formats
  • Ensuring generated content is grounded in actual CV experience without hallucinated achievements or metrics
  • Building robust LaTeX post-processing that handles edge cases like single-paragraph responses and special characters

Outcomes & Impact

  • One-command generation: `covergen generate <url>` produces complete, professional cover letter in seconds
  • Generated letters consistently achieve professional quality with quantified, CV-grounded achievements
  • Modular architecture enabling easy addition of new LLM providers via simple adapter pattern
  • Real-world validated: Successfully generated cover letters for companies like CVS Health, SingleStore, and GitWit