.claude/skills/fastapi-setup/SKILL.md
Initialize FastAPI backend projects with UV package manager, configure project structure, install dependencies, and set up basic FastAPI application. Use when setting up a new FastAPI backend or initializing the backend directory for Phase 2.
npx skillsauth add maneeshanif/todo-spec-driven fastapi-setupInstall 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.
Quick reference for initializing FastAPI backend projects with modern tooling (UV, SQLModel, pytest).
cd backend
# Initialize Python project with UV
uv init --name backend --python 3.13
# Create project structure
mkdir -p src/models src/routers src/services src/middleware src/schemas src/utils tests alembic
# Create __init__.py files
touch src/__init__.py
touch src/models/__init__.py
touch src/routers/__init__.py
touch src/services/__init__.py
touch src/middleware/__init__.py
touch src/schemas/__init__.py
touch src/utils/__init__.py
touch tests/__init__.py
# Core dependencies
uv add fastapi[all]
uv add sqlmodel
uv add psycopg2-binary
uv add python-jose[cryptography]
uv add passlib[bcrypt]
uv add python-dotenv
uv add alembic
# Development dependencies
uv add --dev pytest
uv add --dev pytest-cov
uv add --dev httpx
uv add --dev pytest-asyncio
Create src/main.py:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import os
from dotenv import load_dotenv
load_dotenv()
app = FastAPI(
title="Todo API",
description="RESTful API for Todo Web Application - Phase 2",
version="1.0.0"
)
# CORS configuration
origins = [
os.getenv("FRONTEND_URL", "http://localhost:3000"),
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def root():
return {"message": "Todo API is running", "version": "1.0.0"}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Create src/config.py:
from pydantic_settings import BaseSettings
from functools import lru_cache
class Settings(BaseSettings):
# Database
DATABASE_URL: str
# Authentication
BETTER_AUTH_SECRET: str
JWT_ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_DAYS: int = 7
# CORS
FRONTEND_URL: str = "http://localhost:3000"
# Environment
ENVIRONMENT: str = "development"
class Config:
env_file = ".env"
case_sensitive = True
@lru_cache()
def get_settings():
return Settings()
settings = get_settings()
Create .env.example:
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# Authentication
BETTER_AUTH_SECRET=your-secret-key-here-min-32-characters
# CORS
FRONTEND_URL=http://localhost:3000
# Environment
ENVIRONMENT=development
Create actual .env file:
cp .env.example .env
# Edit .env with actual values
Create src/database.py:
from sqlmodel import create_engine, Session, SQLModel
from sqlalchemy.pool import NullPool
from src.config import settings
engine = create_engine(
settings.DATABASE_URL,
echo=settings.ENVIRONMENT == "development",
poolclass=NullPool, # Let Neon handle pooling
connect_args={
"connect_timeout": 10,
"options": "-c timezone=utc"
}
)
def create_db_and_tables():
"""Create all database tables"""
SQLModel.metadata.create_all(engine)
def get_session():
"""FastAPI dependency for database sessions"""
with Session(engine) as session:
yield session
# Initialize Alembic
alembic init alembic
# Edit alembic.ini - comment out the sqlalchemy.url line
# It will be set from environment variable
# Edit alembic/env.py
Update alembic/env.py:
from logging.config import fileConfig
from sqlmodel import SQLModel
from sqlalchemy import engine_from_config, pool
from alembic import context
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Import all models so Alembic can detect them
from src.models.task import Task # Import as you create models
# Alembic Config object
config = context.config
# Set DATABASE_URL from environment
config.set_main_option("sqlalchemy.url", os.getenv("DATABASE_URL"))
# Interpret the config file for Python logging
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# Set target metadata for autogenerate
target_metadata = SQLModel.metadata
# ... rest of env.py (keep default functions)
Create tests/conftest.py:
import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, create_engine, SQLModel
from sqlmodel.pool import StaticPool
from src.main import app
from src.database import get_session
@pytest.fixture(name="session")
def session_fixture():
engine = create_engine(
"sqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
yield session
@pytest.fixture(name="client")
def client_fixture(session: Session):
def get_session_override():
return session
app.dependency_overrides[get_session] = get_session_override
client = TestClient(app)
yield client
app.dependency_overrides.clear()
Create tests/test_main.py:
def test_root(client):
response = client.get("/")
assert response.status_code == 200
assert "message" in response.json()
def test_health_check(client):
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "healthy"
Create or update pyproject.toml:
[project]
name = "backend"
version = "1.0.0"
description = "Todo API Backend - Phase 2"
requires-python = ">=3.13"
dependencies = [
"fastapi[all]>=0.115.0",
"sqlmodel>=0.0.24",
"psycopg2-binary>=2.9.9",
"python-jose[cryptography]>=3.3.0",
"passlib[bcrypt]>=1.7.4",
"python-dotenv>=1.0.0",
"alembic>=1.13.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.1.0",
"httpx>=0.26.0",
"pytest-asyncio>=0.23.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --cov=src --cov-report=term-missing"
# Run the FastAPI server
cd backend
uv run uvicorn src.main:app --reload --port 8000
# In another terminal, run tests
uv run pytest
# Check code coverage
uv run pytest --cov=src --cov-report=html
After setup, verify:
uv run uvicorn src.main:app --reload starts successfullyuv run pytest runs and passes.env file exists and has DATABASE_URLAfter basic setup:
src/models/src/routers/UV not found:
curl -LsSf https://astral.sh/uv/install.sh | sh
Import errors:
uv run python instead of just pythonDatabase connection errors:
tools
Implement WebSocket service for real-time task synchronization across clients. Use when building real-time updates for Phase 5. (project)
data-ai
Implement Urdu language support with RTL layout, translations, and AI responses in Urdu. Bonus feature (+100 points) for Phase 5. (project)
development
DEPRECATED - Use chatkit-backend skill instead. SSE streaming is now part of the chatkit-backend skill for ChatKit integration.
development
Install and configure Shadcn/ui component library with Radix UI primitives, Aceternity UI effects, set up components, and manage the component registry. Use when adding Shadcn/ui to a Next.js project or installing specific UI components for Phase 2.