skills/asmayaseen/scaffolding-fastapi-dapr/SKILL.md
Build production-grade FastAPI backends with SQLModel, Dapr integration, and JWT authentication. Use when building REST APIs with Neon PostgreSQL, implementing event-driven microservices with Dapr pub/sub, scheduling jobs, or creating CRUD endpoints with JWT/JWKS verification. NOT when building simple scripts or non-microservice architectures.
npx skillsauth add aiskillstore/marketplace scaffolding-fastapi-daprInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build production-grade FastAPI backends with SQLModel, Dapr integration, and JWT authentication.
# Project setup
uv init backend && cd backend
uv add fastapi sqlmodel pydantic httpx python-jose uvicorn
# Development
uv run uvicorn main:app --reload --port 8000
# With Dapr sidecar
dapr run --app-id myapp --app-port 8000 -- uvicorn main:app
from sqlmodel import SQLModel, Field
from datetime import datetime
from typing import Optional, Literal
class TaskBase(SQLModel):
title: str = Field(max_length=200, index=True)
status: Literal["pending", "in_progress", "completed"] = "pending"
class Task(TaskBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
created_at: datetime = Field(default_factory=datetime.now)
class TaskCreate(TaskBase):
pass
class TaskRead(TaskBase):
id: int
created_at: datetime
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine
import os
DATABASE_URL = os.getenv("DATABASE_URL").replace("postgresql://", "postgresql+asyncpg://")
engine = create_async_engine(DATABASE_URL)
async def get_session() -> AsyncSession:
async with AsyncSession(engine) as session:
yield session
from fastapi import FastAPI, Depends, HTTPException
from sqlmodel import select
app = FastAPI()
@app.post("/tasks", response_model=TaskRead, status_code=201)
async def create_task(task: TaskCreate, session: AsyncSession = Depends(get_session)):
db_task = Task.model_validate(task)
session.add(db_task)
await session.commit()
await session.refresh(db_task)
return db_task
@app.get("/tasks/{task_id}", response_model=TaskRead)
async def get_task(task_id: int, session: AsyncSession = Depends(get_session)):
task = await session.get(Task, task_id)
if not task:
raise HTTPException(status_code=404, detail="Not found")
return task
@app.patch("/tasks/{task_id}", response_model=TaskRead)
async def update_task(task_id: int, update: TaskUpdate, session: AsyncSession = Depends(get_session)):
task = await session.get(Task, task_id)
if not task:
raise HTTPException(status_code=404, detail="Not found")
update_data = update.model_dump(exclude_unset=True)
task.sqlmodel_update(update_data)
session.add(task)
await session.commit()
await session.refresh(task)
return task
from jose import jwt
import httpx
JWKS_URL = f"{SSO_URL}/.well-known/jwks.json"
async def get_current_user(authorization: str = Header()):
token = authorization.replace("Bearer ", "")
async with httpx.AsyncClient() as client:
jwks = (await client.get(JWKS_URL)).json()
payload = jwt.decode(token, jwks, algorithms=["RS256"])
return payload
@app.get("/protected")
async def protected_route(user = Depends(get_current_user)):
return {"user": user["sub"]}
See references/fastapi-patterns.md for audit logging, pagination, and OpenAPI configuration.
from fastapi import APIRouter, Request
router = APIRouter(prefix="/dapr", tags=["Dapr"])
@router.get("/subscribe")
async def subscribe():
"""Dapr calls this to discover subscriptions."""
return [{
"pubsubname": "pubsub",
"topic": "task-created",
"route": "/dapr/task-created"
}]
@router.post("/task-created")
async def handle_task_created(request: Request, session: AsyncSession = Depends(get_session)):
# CloudEvent wrapper - data is nested
event = await request.json()
task_data = event.get("data", event) # Handle both wrapped and unwrapped
# Process event
task = Task.model_validate(task_data)
session.add(task)
await session.commit()
return {"status": "processed"}
import httpx
DAPR_URL = "http://localhost:3500"
async def publish_event(topic: str, data: dict):
async with httpx.AsyncClient() as client:
await client.post(
f"{DAPR_URL}/v1.0/publish/pubsub/{topic}",
json=data,
headers={"Content-Type": "application/json"}
)
# Schedule a job via Dapr Jobs API (alpha)
async def schedule_job(name: str, schedule: str, callback_url: str, data: dict):
async with httpx.AsyncClient() as client:
await client.post(
f"{DAPR_URL}/v1.0-alpha1/jobs/{name}",
json={
"schedule": schedule, # "@every 5m" or "0 */5 * * * *"
"data": data,
},
headers={"dapr-app-callback-url": callback_url}
)
# Job callback endpoint
@app.post("/jobs/process")
async def process_job(request: Request):
job_data = await request.json()
# Handle job execution
return {"status": "completed"}
See references/dapr-patterns.md for state management and advanced patterns.
import structlog
structlog.configure(
processors=[
structlog.contextvars.merge_contextvars,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer()
]
)
log = structlog.get_logger()
log.info("task_created", task_id=task.id, user_id=user["sub"])
# Repository: data access only
class TaskRepository:
def __init__(self, session: AsyncSession):
self.session = session
async def create(self, task: TaskCreate) -> Task:
db_task = Task.model_validate(task)
self.session.add(db_task)
await self.session.commit()
return db_task
# Service: business logic
class TaskService:
def __init__(self, repo: TaskRepository):
self.repo = repo
async def create_task(self, task: TaskCreate, user_id: str) -> Task:
# Business logic here
return await self.repo.create(task)
# Dependency injection
def get_task_service(session: AsyncSession = Depends(get_session)):
return TaskService(TaskRepository(session))
@pytest.fixture
async def client(session):
app.dependency_overrides[get_session] = lambda: session
async with AsyncClient(
transport=ASGITransport(app=app),
base_url="http://test"
) as ac:
yield ac
@pytest.mark.anyio
async def test_create_task(client: AsyncClient):
response = await client.post("/tasks", json={"title": "Test"})
assert response.status_code == 201
See references/production-testing.md for full patterns.
backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app
│ ├── database.py # Async engine + session
│ ├── models/ # SQLModel schemas
│ ├── routers/ # API routes
│ ├── repositories/ # Data access layer
│ ├── services/ # Business logic
│ └── dapr/ # Dapr handlers
├── tests/
│ ├── conftest.py # Fixtures
│ └── test_*.py # Test files
├── components/ # Dapr components (k8s)
│ ├── pubsub.yaml
│ └── statestore.yaml
└── pyproject.toml
Run: python3 scripts/verify.py
Expected: ✓ scaffolding-fastapi-dapr skill ready
--library-id /fastapi/fastapi --topic dependenciesdevelopment
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.