# ResumeLens Development Skill Use this skill when building or modifying features in the ResumeLens application. ## Project at a glance - Stack: Go backend (`chi` router) + React 19 + TypeScript + Vite frontend. - Core purpose: accept a resume PDF and job description, call OpenAI, and return structured scoring + feedback. - Backend entrypoint: `cmd/server/main.go`. - Frontend entrypoint: `web/src/main.tsx`. - API endpoint: `POST /api/analyze`. ## Repository map - `cmd/server/main.go`: starts HTTP server on `:3000`, mounts middleware and API routes. - `internal/api/`: CORS + rate-limit middleware and route mounting. - `internal/handlers/analyze.go`: multipart request validation + JSON response. - `internal/services/analyzer.go`: PDF text extraction + OpenAI call + JSON parsing. - `internal/services/prompt.go`: system prompt contract for LLM output. - `internal/models/analysis.go`: canonical backend response schema. - `web/src/pages/`: app routes (`/`, `/upload`, `/demo`, `/results`). - `web/src/components/analysis/`: reusable result UI sections. - `web/src/types/resumeAnalysis.ts`: frontend schema mirror of backend response. - `docker-compose.yml`: local multi-container runtime (`backend` + `frontend` at `:3005`). ## Local development workflow ### Backend - Run: `go run ./cmd/server` - Test: `go test ./...` - Backend listens on `http://localhost:3000`. ### Frontend - Install deps: `cd web && npm ci` - Dev server: `cd web && npm run dev` - Build: `cd web && npm run build` - Lint: `cd web && npm run lint` ### Full stack with Docker - Run: `docker compose up --build` - Frontend served at `http://localhost:3005` - Nginx proxies `/api/*` to backend service (`web/nginx.conf`). ## Configuration and env vars - Backend requires `OPENAI_API_KEY`. - Frontend optionally uses `VITE_API_BASE_URL`. - If unset: dev defaults to `http://localhost:3000`. - If production build: defaults to relative path (`/api/...`) for nginx proxying. Do not hardcode keys or expose secrets in client code. ## API contract (critical) `POST /api/analyze` expects `multipart/form-data`: - `resume`: uploaded file (backend expects a parseable PDF). - `job_description`: non-empty string. Responses: - `200`: JSON matching `AnalysisResult` / `ResumeAnalysisResult`. - `400`: invalid form payload (missing file/job description). - `429`: per-IP rate limit exceeded. - `500`: analysis failure (PDF parse issue, OpenAI issue, JSON parse issue). Keep backend model and frontend type definitions synchronized whenever fields change. ## Existing behavior to preserve - Rate limiting is in-memory and per source IP: max 10 requests/hour. - CORS currently allows: - `http://localhost:5173` - `http://localhost` - `http://localhost:80` - Results page depends on router state; direct navigation to `/results` redirects to `/`. - Download JSON action exists on results page. - Prompt injection output fields are supported in both backend and frontend: - `injection_detected` - `injection_details` ## LLM integration details - LLM call uses `openai-go` chat completions with model `gpt-4o-mini`. - System prompt in `internal/services/prompt.go` requires strict JSON-only output. - Parsing is strict JSON unmarshal into `models.AnalysisResult`. When adding fields: 1. Update `internal/models/analysis.go`. 2. Update prompt JSON contract in `internal/services/prompt.go`. 3. Update `web/src/types/resumeAnalysis.ts`. 4. Update UI components in `web/src/components/analysis/` and pages consuming the data. ## Known implementation quirks - Upload UI currently accepts files with MIME `image/*` in `handleFileSelect`, but the file input element only allows `.pdf`, and backend parser expects PDF bytes. - PDF extraction buffers full file in memory before parsing (`io.ReadAll`), so large-file behavior should be considered when adding limits. - Current rate limiter is process-local; scaling to multiple backend replicas will need shared storage. ## Feature development checklist When implementing a new feature, follow this order: 1. Define data contract impact first (backend model + frontend type). 2. Update API handler/service behavior. 3. Update UI and route behavior. 4. Add or update tests (`go test ./...`; frontend lint/build). 5. Validate end-to-end flow with one manual upload + analyze run. ## Validation commands before shipping - Backend tests: `go test ./...` - Frontend checks: `cd web && npm run lint && npm run build` - Optional full-stack smoke test: `docker compose up --build` ## Deployment notes - CI workflow (`.github/workflows/deploy.yml`) builds and pushes backend/frontend images on pushes to `master`. - Manual image commands are documented in `DEPLOY.md`. If you add runtime dependencies or env vars, update: - Dockerfiles - `docker-compose.yml` - CI workflow - this skill file