2026-04-07 12:26:22 -07:00

131 lines
4.7 KiB
Markdown

# 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