
api-development
by noahtigner
Docker services that I run at home to improve my QoL
SKILL.md
name: api-development description: Guide for developing the API service using Python, FastAPI, Pydantic, and Docker. Use this when creating or modifying API endpoints, models, routers, or backend logic.
API Service Development
This skill covers development of the FastAPI backend services located in /api (main API) and /api_diagnostics (system diagnostics API). Both services follow the same patterns and conventions.
Technology Stack
- Python 3.14 - Core language
- FastAPI - Web framework for building APIs
- Pydantic - Data validation and settings management
- Docker - Containerization
- Redis - Caching layer (via
redis.asyncio) - uvicorn - ASGI server
Project Structure
api/
├── main.py # FastAPI app entry point, router registration, middleware
├── config.py # Settings and configuration
├── requirements.txt # Python dependencies
├── Dockerfile # Docker build configuration
├── cache/ # Redis cache utilities
│ └── router.py
├── github/ # GitHub integration
│ ├── models.py
│ ├── router.py
│ └── retrieval.py
├── pihole/ # Pi-hole integration
│ ├── models.py
│ ├── router.py
│ ├── authentication.py
│ └── retrieval.py
├── nas/ # Synology NAS integration
│ ├── models.py
│ ├── router.py
│ ├── authentication.py
│ ├── constants.py
│ └── retrieval.py
└── [other services]/ # Similar structure for each service
Creating New Endpoints
1. Create Pydantic Models
Define request/response models in models.py:
from pydantic import BaseModel, Field
from typing import Literal
class MyResponseData(BaseModel):
name: str
value: int
status: Literal["active", "inactive"]
class MyResponse(BaseModel):
data: MyResponseData
success: Literal[True]
2. Create Router
Create a router in router.py:
import logging
from fastapi import APIRouter, HTTPException, Request, status
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/myservice",
tags=["MyService"],
)
@router.get("/", tags=["Ping"])
async def get_health(request: Request):
return {"status": "ok"}
@router.get("/data/")
async def get_data(request: Request):
try:
# Implement data retrieval
return {"data": "..."}
except Exception as e:
logger.error(f"Error: {e}")
raise HTTPException(status_code=500, detail=str(e))
3. Register Router
Add the router in main.py:
from api.myservice.router import router as myservice_router
api.include_router(myservice_router)
4. Add Tags Metadata (Optional)
Add to tags_metadata in main.py for OpenAPI documentation:
tags_metadata = [
# ... existing tags
{
"name": "MyService",
"description": "Description of my service",
},
]
Available Tools
Linting and Formatting
Run these commands from the repository root:
# Format Python code with Black
black api/
# Sort imports with isort
isort api/
# Lint with flake8
flake8 api/
Docker Operations
# Build the API container
docker compose -f compose.dev.yml build api
# Run the API in development mode
docker compose -f compose.dev.yml up api
# View API logs
docker compose -f compose.dev.yml logs -f api
Dependency Management
# Install dependencies
pip install -r api/requirements.txt
# Add new dependency (update requirements.txt manually)
# Format: package>=min_version,<max_version
Best Practices
- Use Type Hints: Always use Python type hints for function parameters and return values
- Pydantic Validation: Use Pydantic models for all request/response data
- Async Functions: Use
async deffor endpoint handlers to support async operations - Error Handling: Use
HTTPExceptionwith appropriate status codes - Logging: Use the module logger (
logger = logging.getLogger(__name__)) - Redis Caching: Access Redis via
request.app.state.redis - Router Organization: Each service module should have its own router with a unique prefix
Patterns Used in This Codebase
Authentication Pattern
For services requiring authentication (see nas/authentication.py, pihole/authentication.py):
async def authenticate(credentials: dict) -> str:
# Return session/token
pass
async def logout(session: str) -> None:
pass
Data Retrieval Pattern
Separate retrieval logic from routers (see retrieval.py files):
async def retrieve_data(request: Request) -> dict:
# Fetch and process data
redis = request.app.state.redis
# Check cache, fetch if needed, cache result
return data
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon

