Loading...
Loading...
Trigger when the user wants to create a new FastAPI project, add new features, refactor code, or asks about architectural best practices. This skill enforces 2026 clean architecture with SQLModel, Repository Pattern, full async, and production-ready workflow.
npx skill4agent add chasepassion/skills fastapi-structure-guideasync defasync_sessionmakerawaitDependsAnnotatedtable=Truereferences/sqlmodel-reference.mdBaseSettingstests/app/unit/integration/my-fastapi-project/
├── app/ # Core Application
│ ├── __init__.py
│ ├── main.py # App factory + lifespan
│ ├── api/ # 🌐 API Layer
│ │ ├── __init__.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── api.py # Router aggregation
│ │ └── endpoints/
│ │ ├── __init__.py
│ │ ├── users.py
│ │ └── items.py
│ ├── core/ # ⚙️ Cross-cutting
│ │ ├── __init__.py
│ │ ├── config.py # Settings
│ │ ├── logging.py
│ │ ├── security.py
│ │ └── exceptions.py # Custom HTTP exceptions
│ ├── db/ # 🗄️ Database
│ │ ├── __init__.py
│ │ ├── session.py # async_sessionmaker
│ │ ├── models.py # SQLModel definitions (table=True)
│ │ └── alembic/ # Migrations
│ ├── schemas/ # 📝 API Schemas (DTOs)
│ │ ├── __init__.py
│ │ └── user.py # UserCreate, UserResponse, etc.
│ ├── repositories/ # 🗃️ Data Access Layer (NEW)
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── user_repository.py
│ │ └── item_repository.py
│ ├── services/ # 🧠 Business Logic
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── user_service.py
│ │ └── item_service.py
│ └── dependencies.py # Centralized Depends functions
├── tests/ # ✅ Tests (mirrored)
│ ├── __init__.py
│ ├── conftest.py
│ ├── unit/
│ └── integration/
│ └── api/
│ └── v1/
│ └── endpoints/
│ └── test_users.py
├── .env # Gitignored
├── .env.example
├── .gitignore
├── docker-compose.yaml
├── Dockerfile
├── pyproject.toml # uv + ruff + pyright + pytest-asyncio
└── README.mdapp/schemas/app/repositories/app/services/app/db/models.pytable=Trueapp/core/exceptions.pyreferences/sqlmodel-reference.mdapp/db/models.pyapp/schemas/resource.pyapp/repositories/resource_repository.pyapp/services/resource_service.pyapp/api/v1/endpoints/resource.pyapp/api/v1/api.pytests/integration/references/sqlmodel-reference.md# ✅ Correct
@router.post("/users", response_model=UserResponse)
async def create_user(
user_in: UserCreate,
service: UserService = Depends(get_user_service),
):
return await service.create_user(user_in)# app/repositories/user_repository.py
from sqlmodel.ext.async_session import AsyncSession
from sqlmodel import select
from app.db.models import User
class UserRepository:
def __init__(self, session: AsyncSession):
self.session = session
async def create(self, user: User) -> User:
self.session.add(user)
await self.session.commit()
await self.session.refresh(user)
return user
async def get_by_email(self, email: str) -> User | None:
statement = select(User).where(User.email == email)
result = await self.session.exec(statement)
return result.first()# app/services/user_service.py
class UserService:
def __init__(self, repo: UserRepository):
self.repo = repo
async def create_user(self, data: UserCreate) -> User:
# Business rules here
if await self.repo.get_by_email(data.email):
raise UserAlreadyExists()
user = User(**data.model_dump(exclude={"password"}))
# hash password etc.
return await self.repo.create(user)# app/dependencies.py
from fastapi import Depends
from sqlmodel.ext.async_session import async_sessionmaker
async def get_db() -> AsyncSession:
async with sessionmaker() as session: # from db/session.py
yield session
def get_user_repository(db: AsyncSession = Depends(get_db)) -> UserRepository:
return UserRepository(db)
def get_user_service(repo: UserRepository = Depends(get_user_repository)) -> UserService:
return UserService(repo)# app/db/models.py
from sqlmodel import SQLModel, Field
class User(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
email: str = Field(index=True, unique=True)
hashed_password: str