docs/agent/architecture/backend-guide.md
Lean, local-first FastAPI app for resume tailoring.
| Component | Technology |
|---|---|
| Framework | FastAPI |
| Database | TinyDB (JSON file) |
| AI | LiteLLM (100+ providers) |
| Doc Parsing | markitdown |
| Validation | Pydantic |
apps/backend/app/
├── main.py # Entry point
├── config.py # Settings from env/file
├── database.py # TinyDB wrapper
├── llm.py # Multi-provider LLM
├── routers/ # health, config, resumes, jobs
├── services/ # parser, improver, cover_letter
├── schemas/ # Pydantic models
└── prompts/ # templates.py
db.create_resume(content, content_type, filename, is_master, processed_data)
db.get_resume(resume_id) → dict | None
db.list_resumes() → list[dict]
db.update_resume(resume_id, updates)
db.delete_resume(resume_id) → bool
db.set_master_resume(resume_id)
db.create_job(content, resume_id)
| Feature | Description |
|---|---|
| API Key Passing | Direct to litellm (avoids race conditions) |
| JSON Mode | Auto-enabled for supported providers |
| Retry Logic | 2 retries, temperature 0.1→0.0 |
| Timeouts | 30s (health), 120s (completion), 180s (JSON) |
{variable} for substitution (single braces)GET /api/v1/health # LLM check
GET /api/v1/status # Full status
GET/PUT /api/v1/config/llm-api-key
POST /api/v1/resumes/upload # PDF/DOCX
POST /api/v1/resumes/improve # Tailor (LLM)
GET /api/v1/resumes/{id}/pdf
DELETE /api/v1/resumes/{id}
Upload: File → markitdown → Markdown → LLM parse → JSON → TinyDB
Improve: Resume + Job → Extract keywords (LLM) → Tailor (LLM) → Store
Log details server-side, generic messages to clients:
except Exception as e:
logger.error(f"Failed: {e}")
raise HTTPException(500, "Operation failed.")
cd apps/backend
cp .env.example .env
uv run uvicorn app.main:app --reload --port 8000
app/routers/app/schemas/models.pyapp/main.py