{"name":"build-fastapi-backend","description":"Scaffolds a production-ready Python API with FastAPI - a clear folder layout, Pydantic models, settings from environment variables, dependency injection for the database and auth, async routes and a first pytest suite. Use when the user wants a Python backend, a FastAPI project, a REST API or server in Python, or to tidy a messy FastAPI app.","category":"backend","tags":["python","fastapi","api","rest"],"models":["any"],"proven":false,"passing_families":0,"model_testing":"Not yet model-tested; testing Jan 2027","url":"https://theskillvault.ai/skills/build-fastapi-backend","api_url":"https://theskillvault.ai/api/skills/build-fastapi-backend","raw_url":"https://theskillvault.ai/api/skills/build-fastapi-backend/raw","body":"# Build a FastAPI backend\n\nFastAPI gives you a typed Python API with automatic docs at `/docs`. Start small and keep each layer in its own folder.\n\n## When to use\n- You want a backend in Python rather than JavaScript.\n- You need a REST API for a web or mobile front end.\n- Your FastAPI app has grown into one big `main.py`.\n\n## Steps\n1. Create a project with a virtual environment (or `uv init`) and install `fastapi`, `uvicorn[standard]`, `pydantic-settings` and `pytest` plus `httpx`.\n2. Use this layout:\n\n```text\napp/\n  main.py        # creates the app, includes routers\n  config.py      # Settings read from env vars\n  api/           # one router file per resource\n  models/        # database models\n  schemas/       # Pydantic request and response models\n  services/      # business logic, no HTTP code\ntests/\n```\n\n3. Read settings with `pydantic-settings` from environment variables and a git-ignored `.env`.\n4. Write request and response schemas first. Never return database objects straight to the client.\n5. Add a database session as a dependency with `Depends(get_db)`, so tests can swap it.\n6. Add auth as a dependency too (`Depends(current_user)`), and use it on every private route.\n7. Use `async def` routes with an async driver, or plain `def` with a sync one. Do not mix them in one call path.\n8. Raise `HTTPException` with clear status codes, and add one handler for unexpected errors.\n9. Write tests with `TestClient` or `httpx.AsyncClient` and override dependencies for the database.\n10. Run with `uvicorn app.main:app --reload` and check `/docs`.\n\n```python\n@router.get(\"/items/{item_id}\", response_model=ItemOut)\nasync def read_item(item_id: int, db: Session = Depends(get_db), user: User = Depends(current_user)):\n    item = await items.get_for_user(db, item_id, user.id)\n    if item is None:\n        raise HTTPException(status_code=404, detail=\"Item not found\")\n    return item\n```\n\n## Gotchas\n- Calling a blocking library inside `async def` freezes the whole server. Use an async client or a sync route.\n- Keep `.env` out of git and never print the database password or API keys in logs.\n- Lock CORS to your front-end origins; `allow_origins=[\"*\"]` with cookies is a security hole.\n- Use migrations (Alembic) for schema changes, not `create_all` in production.\n\n## Portability\nWorks with Postgres, SQLite or MySQL through SQLAlchemy or SQLModel. If you use Django or Flask instead, the same split of schemas, services and dependencies still applies.\n\n## Example prompt\n\"Set up a FastAPI backend with users and items, settings from env vars, auth on private routes and pytest tests.\"\n\n## Done when\n- `/docs` shows every route with request and response schemas.\n- Settings come from the environment; no secrets in code.\n- Private routes reject requests without auth.\n- `pytest` passes with the database dependency overridden.\n\n---\nAdapted from \"fastapi-templates\" in wshobson/agents (MIT, Copyright (c) 2024 Seth Hobson). See LICENSE.txt.","files":["LICENSE.txt"],"license":"MIT","license_name":"MIT License","license_url":"https://opensource.org/license/mit","attribution":"Based on work by Seth Hobson (wshobson/agents, fastapi-templates) (Copyright (c) 2024 Seth Hobson, MIT License), https://github.com/wshobson/agents/tree/7e2fb559cf4b824b27f1fec49fe88f7511066d26/plugins/api-scaffolding/skills/fastapi-templates; adapted by TheSkillVault, https://theskillvault.ai","install":{"claude_code":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/raw' -o ~/'.claude/skills/build-fastapi-backend/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/files/LICENSE.txt' -o ~/'.claude/skills/build-fastapi-backend/LICENSE.txt'","cursor":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/raw' -o '.cursor/skills/build-fastapi-backend/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/files/LICENSE.txt' -o '.cursor/skills/build-fastapi-backend/LICENSE.txt'","agents":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/raw' -o '.agents/skills/build-fastapi-backend/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-fastapi-backend/files/LICENSE.txt' -o '.agents/skills/build-fastapi-backend/LICENSE.txt'","mcp_url":"https://theskillvault.ai/mcp","cursor_mcp_deeplink":"cursor://anysphere.cursor-deeplink/mcp/install?name=theskillvault&config=eyJ1cmwiOiJodHRwczovL3RoZXNraWxsdmF1bHQuYWkvbWNwIn0%3D","mcp_config":{"mcpServers":{"theskillvault":{"url":"https://theskillvault.ai/mcp"}}}},"bundles":[],"tested_on":[{"family":"chatgpt","name":"ChatGPT","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"claude","name":"Claude","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"gemini","name":"Gemini","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"grok","name":"Grok","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"llama","name":"Llama","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"deepseek","name":"DeepSeek","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"mistral","name":"Mistral","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"qwen","name":"Qwen","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"kimi","name":"Kimi K","outcome":null,"date":null,"source":null,"counts":false,"stale":false}],"proven_rule":{"threshold":5,"window_days":365,"computed_at":"2026-11-02T03:20:33.817Z"}}