# Srbhr Resume Matcher Backend Dev

> Backend Development

- Skill: `tomevault-io/srbhr-resume-matcher-backend-dev` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/srbhr-resume-matcher-backend-dev`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/srbhr-resume-matcher-backend-dev/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/srbhr-resume-matcher-backend-dev

---


# Backend Development

> Use when creating or modifying FastAPI endpoints, Pydantic schemas, database operations, LLM integrations, or Python service logic.

## Before Writing Code

1. Read `docs/agent/architecture/backend-guide.md` for architecture
2. Read `docs/agent/apis/front-end-apis.md` for API contracts
3. Read `docs/agent/llm-integration.md` for LLM patterns
4. Check existing code in the relevant directory first

## Non-Negotiable Rules

1. **All functions MUST have type hints** - no exceptions
2. **Use `copy.deepcopy()`** for mutable defaults
3. **Log detailed errors server-side**, return generic messages to clients
4. **Use `asyncio.Lock()`** for shared resource initialization
5. **Pass API keys directly** to litellm via `api_key=`, never `os.environ`

## Project Structure

```
apps/backend/app/
├── main.py          # FastAPI app, CORS, lifespan, routers
├── config.py        # Pydantic BaseSettings from env
├── database.py      # TinyDB wrapper (JSON file storage)
├── llm.py           # LiteLLM wrapper (multi-provider)
├── routers/         # API endpoint handlers
├── services/        # Business logic layer
├── schemas/         # Pydantic request/response models
└── prompts/         # LLM prompt templates (Jinja2)
```

## Patterns

### New Endpoint

```python
from fastapi import APIRouter, HTTPException
from app.schemas.my_schema import MyRequest, MyResponse
import logging

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1", tags=["my-feature"])

@router.post("/my-endpoint", response_model=MyResponse)
async def create_thing(request: MyRequest) -> MyResponse:
    try:
        result = await process_data(request)
        return result
    except Exception as e:
        logger.error(f"Failed to create thing: {e}")
        raise HTTPException(status_code=500, detail="Operation failed. Please try again.")
```

### New Schema

```python
from pydantic import BaseModel, Field

class MyRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=200)
    description: str | None = None

class MyResponse(BaseModel):
    id: str
    name: str
    status: str = "created"
```

### Database Operation

```python
import copy
from app.database import get_db

DEFAULT_DATA = {"sections": [], "metadata": {}}

async def get_or_create(doc_id: str) -> dict:
    db = get_db()
    existing = db.get(doc_id)
    if existing:
        return existing
    data = copy.deepcopy(DEFAULT_DATA)  # ALWAYS deepcopy mutable defaults
    db.insert(data)
    return data
```

### LLM Call

```python
from app.llm import get_completion
from app.config import settings

async def improve_text(text: str) -> str:
    prompt = f"Improve this resume text:\n\n{text}"
    result = await get_completion(
        prompt=prompt,
        model=settings.LLM_MODEL,
        api_key=settings.LLM_API_KEY,  # Pass directly, not via env
        json_mode=True,
    )
    return result
```

## Error Handling Pattern

```python
except Exception as e:
    logger.error(f"Operation failed: {e}")  # Detailed for server logs
    raise HTTPException(
        status_code=500,
        detail="Operation failed. Please try again."  # Generic for client
    )
```

## Checklist

- [ ] All functions have type hints
- [ ] Mutable defaults use `copy.deepcopy()`
- [ ] Error handling logs details, returns generic messages
- [ ] New endpoints registered in `main.py` router includes
- [ ] Schemas defined for all request/response bodies
- [ ] API keys passed via `api_key=` parameter

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/srbhr) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

