[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M70NNFJSXAGJEEF7B3P34HPC":3,"skill-same:01M70NNFJSXAGJEEF7B3P34HPC":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":54,"commitSha":55,"skillDirectory":56,"forksCount":57,"repositoryHtmlUrl":58,"repositoryHomepageUrl":59,"ownerHtmlUrl":60,"ownerBlogUrl":61,"ownerDescription":62,"updatedAt":63,"install":64,"resources":77},"01M70NNFJSXAGJEEF7B3P34HPC","fastapi-templates",null,"Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.","shengdabai\u002FTony-Claude-Code-Skills","shengdabai","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F116417419?v=4","01M70F6D2WY5PQV5A92BKYJQEW","Tony Sheng","01M70F6D3GAAAYZ5H4CC1G8VXM",3,"MIT","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fwshobson-agents\u002Fplugins\u002Fapi-scaffolding\u002Fskills\u002Ffastapi-templates\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"fastapi","templates","fastapi templates","use","applications","async","dependency injection","patterns","injection","backend api","dependency","create","api","when","production-ready","new","up","projects","ready","error","2026-11-10 10:12:30",false,"---\nname: fastapi-templates\ndescription: Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.\n---\n\n# FastAPI Project Templates\n\nProduction-ready FastAPI project structures with async patterns, dependency injection, middleware, and best practices for building high-performance APIs.\n\n## When to Use This Skill\n\n- Starting new FastAPI projects from scratch\n- Implementing async REST APIs with Python\n- Building high-performance web services and microservices\n- Creating async applications with PostgreSQL, MongoDB\n- Setting up API projects with proper structure and testing\n\n## Core Concepts\n\n### 1. Project Structure\n\n**Recommended Layout:**\n```\napp\u002F\n├── api\u002F                    # API routes\n│   ├── v1\u002F\n│   │   ├── endpoints\u002F\n│   │   │   ├── users.py\n│   │   │   ├── auth.py\n│   │   │   └── items.py\n│   │   └── router.py\n│   └── dependencies.py     # Shared dependencies\n├── core\u002F                   # Core configuration\n│   ├── config.py\n│   ├── security.py\n│   └── database.py\n├── models\u002F                 # Database models\n│   ├── user.py\n│   └── item.py\n├── schemas\u002F                # Pydantic schemas\n│   ├── user.py\n│   └── item.py\n├── services\u002F               # Business logic\n│   ├── user_service.py\n│   └── auth_service.py\n├── repositories\u002F           # Data access\n│   ├── user_repository.py\n│   └── item_repository.py\n└── main.py                 # Application entry\n```\n\n### 2. Dependency Injection\n\nFastAPI's built-in DI system using `Depends`:\n- Database session management\n- Authentication\u002Fauthorization\n- Shared business logic\n- Configuration injection\n\n### 3. Async Patterns\n\nProper async\u002Fawait usage:\n- Async route handlers\n- Async database operations\n- Async background tasks\n- Async middleware\n\n## Implementation Patterns\n\n### Pattern 1: Complete FastAPI Application\n\n```python\n# main.py\nfrom fastapi import FastAPI, Depends\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom contextlib import asynccontextmanager\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    \"\"\"Application lifespan events.\"\"\"\n    # Startup\n    await database.connect()\n    yield\n    # Shutdown\n    await database.disconnect()\n\napp = FastAPI(\n    title=\"API Template\",\n    version=\"1.0.0\",\n    lifespan=lifespan\n)\n\n# CORS middleware\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"],\n)\n\n# Include routers\nfrom app.api.v1.router import api_router\napp.include_router(api_router, prefix=\"\u002Fapi\u002Fv1\")\n\n# core\u002Fconfig.py\nfrom pydantic_settings import BaseSettings\nfrom functools import lru_cache\n\nclass Settings(BaseSettings):\n    \"\"\"Application settings.\"\"\"\n    DATABASE_URL: str\n    SECRET_KEY: str\n    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30\n    API_V1_STR: str = \"\u002Fapi\u002Fv1\"\n\n    class Config:\n        env_file = \".env\"\n\n@lru_cache()\ndef get_settings() -> Settings:\n    return Settings()\n\n# core\u002Fdatabase.py\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\nfrom app.core.config import get_settings\n\nsettings = get_settings()\n\nengine = create_async_engine(\n    settings.DATABASE_URL,\n    echo=True,\n    future=True\n)\n\nAsyncSessionLocal = sessionmaker(\n    engine,\n    class_=AsyncSession,\n    expire_on_commit=False\n)\n\nBase = declarative_base()\n\nasync def get_db() -> AsyncSession:\n    \"\"\"Dependency for database session.\"\"\"\n    async with AsyncSessionLocal() as session:\n        try:\n            yield session\n            await session.commit()\n        except Exception:\n            await session.rollback()\n            raise\n        finally:\n            await session.close()\n```\n\n### Pattern 2: CRUD Repository Pattern\n\n```python\n# repositories\u002Fbase_repository.py\nfrom typing import Generic, TypeVar, Type, Optional, List\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom sqlalchemy import select\nfrom pydantic import BaseModel\n\nModelType = TypeVar(\"ModelType\")\nCreateSchemaType = TypeVar(\"CreateSchemaType\", bound=BaseModel)\nUpdateSchemaType = TypeVar(\"UpdateSchemaType\", bound=BaseModel)\n\nclass BaseRepository(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):\n    \"\"\"Base repository for CRUD operations.\"\"\"\n\n    def __init__(self, model: Type[ModelType]):\n        self.model = model\n\n    async def get(self, db: AsyncSession, id: int) -> Optional[ModelType]:\n        \"\"\"Get by ID.\"\"\"\n        result = await db.execute(\n            select(self.model).where(self.model.id == id)\n        )\n        return result.scalars().first()\n\n    async def get_multi(\n        self,\n        db: AsyncSession,\n        skip: int = 0,\n        limit: int = 100\n    ) -> List[ModelType]:\n        \"\"\"Get multiple records.\"\"\"\n        result = await db.execute(\n            select(self.model).offset(skip).limit(limit)\n        )\n        return result.scalars().all()\n\n    async def create(\n        self,\n        db: AsyncSession,\n        obj_in: CreateSchemaType\n    ) -> ModelType:\n        \"\"\"Create new record.\"\"\"\n        db_obj = self.model(**obj_in.dict())\n        db.add(db_obj)\n        await db.flush()\n        await db.refresh(db_obj)\n        return db_obj\n\n    async def update(\n        self,\n        db: AsyncSession,\n        db_obj: ModelType,\n        obj_in: UpdateSchemaType\n    ) -> ModelType:\n        \"\"\"Update record.\"\"\"\n        update_data = obj_in.dict(exclude_unset=True)\n        for field, value in update_data.items():\n            setattr(db_obj, field, value)\n        await db.flush()\n        await db.refresh(db_obj)\n        return db_obj\n\n    async def delete(self, db: AsyncSession, id: int) -> bool:\n        \"\"\"Delete record.\"\"\"\n        obj = await self.get(db, id)\n        if obj:\n            await db.delete(obj)\n            return True\n        return False\n\n# repositories\u002Fuser_repository.py\nfrom app.repositories.base_repository import BaseRepository\nfrom app.models.user import User\nfrom app.schemas.user import UserCreate, UserUpdate\n\nclass UserRepository(BaseRepository[User, UserCreate, UserUpdate]):\n    \"\"\"User-specific repository.\"\"\"\n\n    async def get_by_email(self, db: AsyncSession, email: str) -> Optional[User]:\n        \"\"\"Get user by email.\"\"\"\n        result = await db.execute(\n            select(User).where(User.email == email)\n        )\n        return result.scalars().first()\n\n    async def is_active(self, db: AsyncSession, user_id: int) -> bool:\n        \"\"\"Check if user is active.\"\"\"\n        user = await self.get(db, user_id)\n        return user.is_active if user else False\n\nuser_repository = UserRepository(User)\n```\n\n### Pattern 3: Service Layer\n\n```python\n# services\u002Fuser_service.py\nfrom typing import Optional\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom app.repositories.user_repository import user_repository\nfrom app.schemas.user import UserCreate, UserUpdate, User\nfrom app.core.security import get_password_hash, verify_password\n\nclass UserService:\n    \"\"\"Business logic for users.\"\"\"\n\n    def __init__(self):\n        self.repository = user_repository\n\n    async def create_user(\n        self,\n        db: AsyncSession,\n        user_in: UserCreate\n    ) -> User:\n        \"\"\"Create new user with hashed password.\"\"\"\n        # Check if email exists\n        existing = await self.repository.get_by_email(db, user_in.email)\n        if existing:\n            raise ValueError(\"Email already registered\")\n\n        # Hash password\n        user_in_dict = user_in.dict()\n        user_in_dict[\"hashed_password\"] = get_password_hash(user_in_dict.pop(\"password\"))\n\n        # Create user\n        user = await self.repository.create(db, UserCreate(**user_in_dict))\n        return user\n\n    async def authenticate(\n        self,\n        db: AsyncSession,\n        email: str,\n        password: str\n    ) -> Optional[User]:\n        \"\"\"Authenticate user.\"\"\"\n        user = await self.repository.get_by_email(db, email)\n        if not user:\n            return None\n        if not verify_password(password, user.hashed_password):\n            return None\n        return user\n\n    async def update_user(\n        self,\n        db: AsyncSession,\n        user_id: int,\n        user_in: UserUpdate\n    ) -> Optional[User]:\n        \"\"\"Update user.\"\"\"\n        user = await self.repository.get(db, user_id)\n        if not user:\n            return None\n\n        if user_in.password:\n            user_in_dict = user_in.dict(exclude_unset=True)\n            user_in_dict[\"hashed_password\"] = get_password_hash(\n                user_in_dict.pop(\"password\")\n            )\n            user_in = UserUpdate(**user_in_dict)\n\n        return await self.repository.update(db, user, user_in)\n\nuser_service = UserService()\n```\n\n### Pattern 4: API Endpoints with Dependencies\n\n```python\n# api\u002Fv1\u002Fendpoints\u002Fusers.py\nfrom fastapi import APIRouter, Depends, HTTPException, status\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom typing import List\n\nfrom app.core.database import get_db\nfrom app.schemas.user import User, UserCreate, UserUpdate\nfrom app.services.user_service import user_service\nfrom app.api.dependencies import get_current_user\n\nrouter = APIRouter()\n\n@router.post(\"\u002F\", response_model=User, status_code=status.HTTP_201_CREATED)\nasync def create_user(\n    user_in: UserCreate,\n    db: AsyncSession = Depends(get_db)\n):\n    \"\"\"Create new user.\"\"\"\n    try:\n        user = await user_service.create_user(db, user_in)\n        return user\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n\n@router.get(\"\u002Fme\", response_model=User)\nasync def read_current_user(\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Get current user.\"\"\"\n    return current_user\n\n@router.get(\"\u002F{user_id}\", response_model=User)\nasync def read_user(\n    user_id: int,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Get user by ID.\"\"\"\n    user = await user_service.repository.get(db, user_id)\n    if not user:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return user\n\n@router.patch(\"\u002F{user_id}\", response_model=User)\nasync def update_user(\n    user_id: int,\n    user_in: UserUpdate,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Update user.\"\"\"\n    if current_user.id != user_id:\n        raise HTTPException(status_code=403, detail=\"Not authorized\")\n\n    user = await user_service.update_user(db, user_id, user_in)\n    if not user:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return user\n\n@router.delete(\"\u002F{user_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_user(\n    user_id: int,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Delete user.\"\"\"\n    if current_user.id != user_id:\n        raise HTTPException(status_code=403, detail=\"Not authorized\")\n\n    deleted = await user_service.repository.delete(db, user_id)\n    if not deleted:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n```\n\n### Pattern 5: Authentication & Authorization\n\n```python\n# core\u002Fsecurity.py\nfrom datetime import datetime, timedelta\nfrom typing import Optional\nfrom jose import JWTError, jwt\nfrom passlib.context import CryptContext\nfrom app.core.config import get_settings\n\nsettings = get_settings()\npwd_context = CryptContext(schemes=[\"bcrypt\"], deprecated=\"auto\")\n\nALGORITHM = \"HS256\"\n\ndef create_access_token(data: dict, expires_delta: Optional[timedelta] = None):\n    \"\"\"Create JWT access token.\"\"\"\n    to_encode = data.copy()\n    if expires_delta:\n        expire = datetime.utcnow() + expires_delta\n    else:\n        expire = datetime.utcnow() + timedelta(minutes=15)\n    to_encode.update({\"exp\": expire})\n    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM)\n    return encoded_jwt\n\ndef verify_password(plain_password: str, hashed_password: str) -> bool:\n    \"\"\"Verify password against hash.\"\"\"\n    return pwd_context.verify(plain_password, hashed_password)\n\ndef get_password_hash(password: str) -> str:\n    \"\"\"Hash password.\"\"\"\n    return pwd_context.hash(password)\n\n# api\u002Fdependencies.py\nfrom fastapi import Depends, HTTPException, status\nfrom fastapi.security import OAuth2PasswordBearer\nfrom jose import JWTError, jwt\nfrom sqlalchemy.ext.asyncio import AsyncSession\n\nfrom app.core.database import get_db\nfrom app.core.security import ALGORITHM\nfrom app.core.config import get_settings\nfrom app.repositories.user_repository import user_repository\n\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=f\"{settings.API_V1_STR}\u002Fauth\u002Flogin\")\n\nasync def get_current_user(\n    db: AsyncSession = Depends(get_db),\n    token: str = Depends(oauth2_scheme)\n):\n    \"\"\"Get current authenticated user.\"\"\"\n    credentials_exception = HTTPException(\n        status_code=status.HTTP_401_UNAUTHORIZED,\n        detail=\"Could not validate credentials\",\n        headers={\"WWW-Authenticate\": \"Bearer\"},\n    )\n\n    try:\n        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])\n        user_id: int = payload.get(\"sub\")\n        if user_id is None:\n            raise credentials_exception\n    except JWTError:\n        raise credentials_exception\n\n    user = await user_repository.get(db, user_id)\n    if user is None:\n        raise credentials_exception\n\n    return user\n```\n\n## Testing\n\n```python\n# tests\u002Fconftest.py\nimport pytest\nimport asyncio\nfrom httpx import AsyncClient\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\nfrom sqlalchemy.orm import sessionmaker\n\nfrom app.main import app\nfrom app.core.database import get_db, Base\n\nTEST_DATABASE_URL = \"sqlite+aiosqlite:\u002F\u002F\u002F:memory:\"\n\n@pytest.fixture(scope=\"session\")\ndef event_loop():\n    loop = asyncio.get_event_loop_policy().new_event_loop()\n    yield loop\n    loop.close()\n\n@pytest.fixture\nasync def db_session():\n    engine = create_async_engine(TEST_DATABASE_URL, echo=True)\n    async with engine.begin() as conn:\n        await conn.run_sync(Base.metadata.create_all)\n\n    AsyncSessionLocal = sessionmaker(\n        engine, class_=AsyncSession, expire_on_commit=False\n    )\n\n    async with AsyncSessionLocal() as session:\n        yield session\n\n@pytest.fixture\nasync def client(db_session):\n    async def override_get_db():\n        yield db_session\n\n    app.dependency_overrides[get_db] = override_get_db\n\n    async with AsyncClient(app=app, base_url=\"http:\u002F\u002Ftest\") as client:\n        yield client\n\n# tests\u002Ftest_users.py\nimport pytest\n\n@pytest.mark.asyncio\nasync def test_create_user(client):\n    response = await client.post(\n        \"\u002Fapi\u002Fv1\u002Fusers\u002F\",\n        json={\n            \"email\": \"test@example.com\",\n            \"password\": \"testpass123\",\n            \"name\": \"Test User\"\n        }\n    )\n    assert response.status_code == 201\n    data = response.json()\n    assert data[\"email\"] == \"test@example.com\"\n    assert \"id\" in data\n```\n\n## Resources\n\n- **references\u002Ffastapi-architecture.md**: Detailed architecture guide\n- **references\u002Fasync-best-practices.md**: Async\u002Fawait patterns\n- **references\u002Ftesting-strategies.md**: Comprehensive testing guide\n- **assets\u002Fproject-template\u002F**: Complete FastAPI project\n- **assets\u002Fdocker-compose.yml**: Development environment setup\n\n## Best Practices\n\n1. **Async All The Way**: Use async for database, external APIs\n2. **Dependency Injection**: Leverage FastAPI's DI system\n3. **Repository Pattern**: Separate data access from business logic\n4. **Service Layer**: Keep business logic out of routes\n5. **Pydantic Schemas**: Strong typing for request\u002Fresponse\n6. **Error Handling**: Consistent error responses\n7. **Testing**: Test all layers independently\n\n## Common Pitfalls\n\n- **Blocking Code in Async**: Using synchronous database drivers\n- **No Service Layer**: Business logic in route handlers\n- **Missing Type Hints**: Loses FastAPI's benefits\n- **Ignoring Sessions**: Not properly managing database sessions\n- **No Testing**: Skipping integration tests\n- **Tight Coupling**: Direct database access in routes\n","# FastAPI Project Templates\n\nProduction-ready FastAPI project structures with async patterns, dependency injection, middleware, and best practices for building high-performance APIs.\n\n## When to Use This Skill\n\n- Starting new FastAPI projects from scratch\n- Implementing async REST APIs with Python\n- Building high-performance web services and microservices\n- Creating async applications with PostgreSQL, MongoDB\n- Setting up API projects with proper structure and testing\n\n## Core Concepts\n\n### 1. Project Structure\n\n**Recommended Layout:**\n```\napp\u002F\n├── api\u002F                    # API routes\n│   ├── v1\u002F\n│   │   ├── endpoints\u002F\n│   │   │   ├── users.py\n│   │   │   ├── auth.py\n│   │   │   └── items.py\n│   │   └── router.py\n│   └── dependencies.py     # Shared dependencies\n├── core\u002F                   # Core configuration\n│   ├── config.py\n│   ├── security.py\n│   └── database.py\n├── models\u002F                 # Database models\n│   ├── user.py\n│   └── item.py\n├── schemas\u002F                # Pydantic schemas\n│   ├── user.py\n│   └── item.py\n├── services\u002F               # Business logic\n│   ├── user_service.py\n│   └── auth_service.py\n├── repositories\u002F           # Data access\n│   ├── user_repository.py\n│   └── item_repository.py\n└── main.py                 # Application entry\n```\n\n### 2. Dependency Injection\n\nFastAPI's built-in DI system using `Depends`:\n- Database session management\n- Authentication\u002Fauthorization\n- Shared business logic\n- Configuration injection\n\n### 3. Async Patterns\n\nProper async\u002Fawait usage:\n- Async route handlers\n- Async database operations\n- Async background tasks\n- Async middleware\n\n## Implementation Patterns\n\n### Pattern 1: Complete FastAPI Application\n\n```python\n# main.py\nfrom fastapi import FastAPI, Depends\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom contextlib import asynccontextmanager\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    \"\"\"Application lifespan events.\"\"\"\n    # Startup\n    await database.connect()\n    yield\n    # Shutdown\n    await database.disconnect()\n\napp = FastAPI(\n    title=\"API Template\",\n    version=\"1.0.0\",\n    lifespan=lifespan\n)\n\n# CORS middleware\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"],\n)\n\n# Include routers\nfrom app.api.v1.router import api_router\napp.include_router(api_router, prefix=\"\u002Fapi\u002Fv1\")\n\n# core\u002Fconfig.py\nfrom pydantic_settings import BaseSettings\nfrom functools import lru_cache\n\nclass Settings(BaseSettings):\n    \"\"\"Application settings.\"\"\"\n    DATABASE_URL: str\n    SECRET_KEY: str\n    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30\n    API_V1_STR: str = \"\u002Fapi\u002Fv1\"\n\n    class Config:\n        env_file = \".env\"\n\n@lru_cache()\ndef get_settings() -> Settings:\n    return Settings()\n\n# core\u002Fdatabase.py\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\nfrom app.core.config import get_settings\n\nsettings = get_settings()\n\nengine = create_async_engine(\n    settings.DATABASE_URL,\n    echo=True,\n    future=True\n)\n\nAsyncSessionLocal = sessionmaker(\n    engine,\n    class_=AsyncSession,\n    expire_on_commit=False\n)\n\nBase = declarative_base()\n\nasync def get_db() -> AsyncSession:\n    \"\"\"Dependency for database session.\"\"\"\n    async with AsyncSessionLocal() as session:\n        try:\n            yield session\n            await session.commit()\n        except Exception:\n            await session.rollback()\n            raise\n        finally:\n            await session.close()\n```\n\n### Pattern 2: CRUD Repository Pattern\n\n```python\n# repositories\u002Fbase_repository.py\nfrom typing import Generic, TypeVar, Type, Optional, List\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom sqlalchemy import select\nfrom pydantic import BaseModel\n\nModelType = TypeVar(\"ModelType\")\nCreateSchemaType = TypeVar(\"CreateSchemaType\", bound=BaseModel)\nUpdateSchemaType = TypeVar(\"UpdateSchemaType\", bound=BaseModel)\n\nclass BaseRepository(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):\n    \"\"\"Base repository for CRUD operations.\"\"\"\n\n    def __init__(self, model: Type[ModelType]):\n        self.model = model\n\n    async def get(self, db: AsyncSession, id: int) -> Optional[ModelType]:\n        \"\"\"Get by ID.\"\"\"\n        result = await db.execute(\n            select(self.model).where(self.model.id == id)\n        )\n        return result.scalars().first()\n\n    async def get_multi(\n        self,\n        db: AsyncSession,\n        skip: int = 0,\n        limit: int = 100\n    ) -> List[ModelType]:\n        \"\"\"Get multiple records.\"\"\"\n        result = await db.execute(\n            select(self.model).offset(skip).limit(limit)\n        )\n        return result.scalars().all()\n\n    async def create(\n        self,\n        db: AsyncSession,\n        obj_in: CreateSchemaType\n    ) -> ModelType:\n        \"\"\"Create new record.\"\"\"\n        db_obj = self.model(**obj_in.dict())\n        db.add(db_obj)\n        await db.flush()\n        await db.refresh(db_obj)\n        return db_obj\n\n    async def update(\n        self,\n        db: AsyncSession,\n        db_obj: ModelType,\n        obj_in: UpdateSchemaType\n    ) -> ModelType:\n        \"\"\"Update record.\"\"\"\n        update_data = obj_in.dict(exclude_unset=True)\n        for field, value in update_data.items():\n            setattr(db_obj, field, value)\n        await db.flush()\n        await db.refresh(db_obj)\n        return db_obj\n\n    async def delete(self, db: AsyncSession, id: int) -> bool:\n        \"\"\"Delete record.\"\"\"\n        obj = await self.get(db, id)\n        if obj:\n            await db.delete(obj)\n            return True\n        return False\n\n# repositories\u002Fuser_repository.py\nfrom app.repositories.base_repository import BaseRepository\nfrom app.models.user import User\nfrom app.schemas.user import UserCreate, UserUpdate\n\nclass UserRepository(BaseRepository[User, UserCreate, UserUpdate]):\n    \"\"\"User-specific repository.\"\"\"\n\n    async def get_by_email(self, db: AsyncSession, email: str) -> Optional[User]:\n        \"\"\"Get user by email.\"\"\"\n        result = await db.execute(\n            select(User).where(User.email == email)\n        )\n        return result.scalars().first()\n\n    async def is_active(self, db: AsyncSession, user_id: int) -> bool:\n        \"\"\"Check if user is active.\"\"\"\n        user = await self.get(db, user_id)\n        return user.is_active if user else False\n\nuser_repository = UserRepository(User)\n```\n\n### Pattern 3: Service Layer\n\n```python\n# services\u002Fuser_service.py\nfrom typing import Optional\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom app.repositories.user_repository import user_repository\nfrom app.schemas.user import UserCreate, UserUpdate, User\nfrom app.core.security import get_password_hash, verify_password\n\nclass UserService:\n    \"\"\"Business logic for users.\"\"\"\n\n    def __init__(self):\n        self.repository = user_repository\n\n    async def create_user(\n        self,\n        db: AsyncSession,\n        user_in: UserCreate\n    ) -> User:\n        \"\"\"Create new user with hashed password.\"\"\"\n        # Check if email exists\n        existing = await self.repository.get_by_email(db, user_in.email)\n        if existing:\n            raise ValueError(\"Email already registered\")\n\n        # Hash password\n        user_in_dict = user_in.dict()\n        user_in_dict[\"hashed_password\"] = get_password_hash(user_in_dict.pop(\"password\"))\n\n        # Create user\n        user = await self.repository.create(db, UserCreate(**user_in_dict))\n        return user\n\n    async def authenticate(\n        self,\n        db: AsyncSession,\n        email: str,\n        password: str\n    ) -> Optional[User]:\n        \"\"\"Authenticate user.\"\"\"\n        user = await self.repository.get_by_email(db, email)\n        if not user:\n            return None\n        if not verify_password(password, user.hashed_password):\n            return None\n        return user\n\n    async def update_user(\n        self,\n        db: AsyncSession,\n        user_id: int,\n        user_in: UserUpdate\n    ) -> Optional[User]:\n        \"\"\"Update user.\"\"\"\n        user = await self.repository.get(db, user_id)\n        if not user:\n            return None\n\n        if user_in.password:\n            user_in_dict = user_in.dict(exclude_unset=True)\n            user_in_dict[\"hashed_password\"] = get_password_hash(\n                user_in_dict.pop(\"password\")\n            )\n            user_in = UserUpdate(**user_in_dict)\n\n        return await self.repository.update(db, user, user_in)\n\nuser_service = UserService()\n```\n\n### Pattern 4: API Endpoints with Dependencies\n\n```python\n# api\u002Fv1\u002Fendpoints\u002Fusers.py\nfrom fastapi import APIRouter, Depends, HTTPException, status\nfrom sqlalchemy.ext.asyncio import AsyncSession\nfrom typing import List\n\nfrom app.core.database import get_db\nfrom app.schemas.user import User, UserCreate, UserUpdate\nfrom app.services.user_service import user_service\nfrom app.api.dependencies import get_current_user\n\nrouter = APIRouter()\n\n@router.post(\"\u002F\", response_model=User, status_code=status.HTTP_201_CREATED)\nasync def create_user(\n    user_in: UserCreate,\n    db: AsyncSession = Depends(get_db)\n):\n    \"\"\"Create new user.\"\"\"\n    try:\n        user = await user_service.create_user(db, user_in)\n        return user\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n\n@router.get(\"\u002Fme\", response_model=User)\nasync def read_current_user(\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Get current user.\"\"\"\n    return current_user\n\n@router.get(\"\u002F{user_id}\", response_model=User)\nasync def read_user(\n    user_id: int,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Get user by ID.\"\"\"\n    user = await user_service.repository.get(db, user_id)\n    if not user:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return user\n\n@router.patch(\"\u002F{user_id}\", response_model=User)\nasync def update_user(\n    user_id: int,\n    user_in: UserUpdate,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Update user.\"\"\"\n    if current_user.id != user_id:\n        raise HTTPException(status_code=403, detail=\"Not authorized\")\n\n    user = await user_service.update_user(db, user_id, user_in)\n    if not user:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return user\n\n@router.delete(\"\u002F{user_id}\", status_code=status.HTTP_204_NO_CONTENT)\nasync def delete_user(\n    user_id: int,\n    db: AsyncSession = Depends(get_db),\n    current_user: User = Depends(get_current_user)\n):\n    \"\"\"Delete user.\"\"\"\n    if current_user.id != user_id:\n        raise HTTPException(status_code=403, detail=\"Not authorized\")\n\n    deleted = await user_service.repository.delete(db, user_id)\n    if not deleted:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n```\n\n### Pattern 5: Authentication & Authorization\n\n```python\n# core\u002Fsecurity.py\nfrom datetime import datetime, timedelta\nfrom typing import Optional\nfrom jose import JWTError, jwt\nfrom passlib.context import CryptContext\nfrom app.core.config import get_settings\n\nsettings = get_settings()\npwd_context = CryptContext(schemes=[\"bcrypt\"], deprecated=\"auto\")\n\nALGORITHM = \"HS256\"\n\ndef create_access_token(data: dict, expires_delta: Optional[timedelta] = None):\n    \"\"\"Create JWT access token.\"\"\"\n    to_encode = data.copy()\n    if expires_delta:\n        expire = datetime.utcnow() + expires_delta\n    else:\n        expire = datetime.utcnow() + timedelta(minutes=15)\n    to_encode.update({\"exp\": expire})\n    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM)\n    return encoded_jwt\n\ndef verify_password(plain_password: str, hashed_password: str) -> bool:\n    \"\"\"Verify password against hash.\"\"\"\n    return pwd_context.verify(plain_password, hashed_password)\n\ndef get_password_hash(password: str) -> str:\n    \"\"\"Hash password.\"\"\"\n    return pwd_context.hash(password)\n\n# api\u002Fdependencies.py\nfrom fastapi import Depends, HTTPException, status\nfrom fastapi.security import OAuth2PasswordBearer\nfrom jose import JWTError, jwt\nfrom sqlalchemy.ext.asyncio import AsyncSession\n\nfrom app.core.database import get_db\nfrom app.core.security import ALGORITHM\nfrom app.core.config import get_settings\nfrom app.repositories.user_repository import user_repository\n\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=f\"{settings.API_V1_STR}\u002Fauth\u002Flogin\")\n\nasync def get_current_user(\n    db: AsyncSession = Depends(get_db),\n    token: str = Depends(oauth2_scheme)\n):\n    \"\"\"Get current authenticated user.\"\"\"\n    credentials_exception = HTTPException(\n        status_code=status.HTTP_401_UNAUTHORIZED,\n        detail=\"Could not validate credentials\",\n        headers={\"WWW-Authenticate\": \"Bearer\"},\n    )\n\n    try:\n        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])\n        user_id: int = payload.get(\"sub\")\n        if user_id is None:\n            raise credentials_exception\n    except JWTError:\n        raise credentials_exception\n\n    user = await user_repository.get(db, user_id)\n    if user is None:\n        raise credentials_exception\n\n    return user\n```\n\n## Testing\n\n```python\n# tests\u002Fconftest.py\nimport pytest\nimport asyncio\nfrom httpx import AsyncClient\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\nfrom sqlalchemy.orm import sessionmaker\n\nfrom app.main import app\nfrom app.core.database import get_db, Base\n\nTEST_DATABASE_URL = \"sqlite+aiosqlite:\u002F\u002F\u002F:memory:\"\n\n@pytest.fixture(scope=\"session\")\ndef event_loop():\n    loop = asyncio.get_event_loop_policy().new_event_loop()\n    yield loop\n    loop.close()\n\n@pytest.fixture\nasync def db_session():\n    engine = create_async_engine(TEST_DATABASE_URL, echo=True)\n    async with engine.begin() as conn:\n        await conn.run_sync(Base.metadata.create_all)\n\n    AsyncSessionLocal = sessionmaker(\n        engine, class_=AsyncSession, expire_on_commit=False\n    )\n\n    async with AsyncSessionLocal() as session:\n        yield session\n\n@pytest.fixture\nasync def client(db_session):\n    async def override_get_db():\n        yield db_session\n\n    app.dependency_overrides[get_db] = override_get_db\n\n    async with AsyncClient(app=app, base_url=\"http:\u002F\u002Ftest\") as client:\n        yield client\n\n# tests\u002Ftest_users.py\nimport pytest\n\n@pytest.mark.asyncio\nasync def test_create_user(client):\n    response = await client.post(\n        \"\u002Fapi\u002Fv1\u002Fusers\u002F\",\n        json={\n            \"email\": \"test@example.com\",\n            \"password\": \"testpass123\",\n            \"name\": \"Test User\"\n        }\n    )\n    assert response.status_code == 201\n    data = response.json()\n    assert data[\"email\"] == \"test@example.com\"\n    assert \"id\" in data\n```\n\n## Resources\n\n- **references\u002Ffastapi-architecture.md**: Detailed architecture guide\n- **references\u002Fasync-best-practices.md**: Async\u002Fawait patterns\n- **references\u002Ftesting-strategies.md**: Comprehensive testing guide\n- **assets\u002Fproject-template\u002F**: Complete FastAPI project\n- **assets\u002Fdocker-compose.yml**: Development environment setup\n\n## Best Practices\n\n1. **Async All The Way**: Use async for database, external APIs\n2. **Dependency Injection**: Leverage FastAPI's DI system\n3. **Repository Pattern**: Separate data access from business logic\n4. **Service Layer**: Keep business logic out of routes\n5. **Pydantic Schemas**: Strong typing for request\u002Fresponse\n6. **Error Handling**: Consistent error responses\n7. **Testing**: Test all layers independently\n\n## Common Pitfalls\n\n- **Blocking Code in Async**: Using synchronous database drivers\n- **No Service Layer**: Business logic in route handlers\n- **Missing Type Hints**: Loses FastAPI's benefits\n- **Ignoring Sessions**: Not properly managing database sessions\n- **No Testing**: Skipping integration tests\n- **Tight Coupling**: Direct database access in routes\n",{"name":5,"description":7},"main","7850740bd837adb32f0a109ab2af82482196c6f2","skills\u002Fwshobson-agents\u002Fplugins\u002Fapi-scaffolding\u002Fskills\u002Ffastapi-templates",1,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills","https:\u002F\u002Fzturnsgo.com","https:\u002F\u002Fgithub.com\u002Fshengdabai","https:\u002F\u002Fzturnsgo.com\u002F","AI × education creator — producer, not consumer. Taught 6,000+ learners; shipping learning tools & daily essays with Claude Code, practicing @xiaolai's way 🥋","2026-11-01 21:28:23",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add shengdabai\u002FTony-Claude-Code-Skills --skill fastapi-templates",{"tool":70,"command":71},"bunx","bunx skills add shengdabai\u002FTony-Claude-Code-Skills --skill fastapi-templates",{"tool":73,"command":74},"pnpm","pnpm dlx skills add shengdabai\u002FTony-Claude-Code-Skills --skill fastapi-templates","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fwshobson-agents\u002Fplugins\u002Fapi-scaffolding\u002Fskills\u002Ffastapi-templates\u002FSKILL.md",true,[],[79,96,126,150,172,192],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":88,"publishedAt":49},"01M70P17DAD4C1C47NPH6A96EM","xiaolai-methodology","以李笑来(Li Xiaolai)的思考方式、方法论与表达风格,为用户做全方位 1-on-1 教练指导,覆盖创业、赚钱、投资、学习、自学、读书写作、用 AI、以及人生心态与自我管理。当用户提到 \"李笑来\"、\"笑来\"、\"笑来老师\"、\"扮演李笑来\"、\"找笑来聊聊\"、\"笑来怎么看\"、\"xiaolai\"、\"把时间当作朋友\"、\"通往财富自由之路\"、\"定投改变命运\"、\"韭菜的自我修养\"、\"自学是门手艺\"、\"让时间陪你慢慢变富\"、\"七年就是一辈子\"、\"元认知\"、\"活在未来\"、\"复利\u002F长期主义\"、\"践行\"、\"痴迷改进\"、\"个人商业模式\u002F出售时间\"、\"睡后收入\"、\"定投\"、\"财富自由\"、\"操作系统升级\"、\"最少必要知识\"、\"北极星提示词\"、\"用 AI 该怎么学\u002F思考\" 等任一触发词,或当用户带着关于创业\u002F赚钱\u002F投资\u002F学习\u002F职业\u002F重大人生决策的困惑、希望被人用笑来式的「逻辑 + 大白话 + 类比 + 重新定义 + 践行导向」来点醒和指导时,自动进入李笑来教练模式。","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fxiaolai-methodology\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",[89,90,91,92,93,94,95],"methodology","xiaolai","xiaolai methodology","朋友","投资","writing","收入",{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":106,"publishedAt":49},"01M70P13NB9YP7ACJR1S861CDS","zread","Produce and consume a wiki-style knowledge base for a code repository via the `zread` CLI and its on-disk output under `.\u002F.zread\u002Fwiki\u002F`. Use this skill whenever the user wants to understand, onboard onto, explore, summarize, map, or get an overview of an unfamiliar codebase; asks for architecture docs, a project wiki, a repo walkthrough, module\u002Fpackage explanations, or \"what does this repo do\"; wants to generate, regenerate, resume, browse, or serve code documentation locally; or mentions zread \u002F zread.ai directly. Also use it proactively before diving into a large unknown repo — if `.\u002F.zread\u002Fwiki\u002Fcurrent` exists, read the generated pages instead of crawling source file-by-file; if it doesn't, consider offering to run `zread generate`. The trigger is the intent (understand a codebase through generated docs), not the literal word \"zread\".","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fzread\u002FSKILL.md",[102,105],{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[98,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125],"knowledge","wiki","explore","walkthrough","project","get","knowledge base","run","generate","intent","cli","map","documentation","project wiki","disk","architecture","code","unknown","generated",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":136,"publishedAt":49},"01M70P10S4SWMZQ8BJAFBFDRW3","youtube","Launch the YouTube Creator Agent to auto-generate videos.\nUse when: user types \u002Fyoutube, wants to create YouTube videos,\ngenerate video content, or upload to YouTube.\nKeywords: youtube, video, 视频, 创作视频, 发布视频","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube\u002FSKILL.md",[132,133],{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":134,"categoryName":135,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000036","内容创作者",[128,137,138,139,140,141,142,143,115,144,40,145,42,32,146,147,148,149],"user","content","视频","creator","generate video","videos","launch","video content","upload","auto","types","Video","创作",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":157,"publishedAt":49},"01M70P0YE95D8BACZCGV8BK90K","youtube-script-sync","Sync, update, or optimize Tony's GetNote knowledge base `Youtube视频逐字稿` by turning each parent recording or first-person idea note into an idempotent child note containing a directly recordable YouTube long-video or Shorts script. Use when the user says “更新\u002F同步\u002F优化 Youtube视频逐字稿知识库”, or says “更新\u002F同步\u002F优化该知识库” while this knowledge base is the active context.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube-script-sync\u002FSKILL.md",[156],{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},[158,159,128,160,161,148,162,163,164,165,166,167,168,169,113,170,42,32,107,171],"sync","script","youtube script sync","recording","shorts","first","base","person","update","active","child","optimize","idempotent","long",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":182,"publishedAt":49},"01M70P0WMV5XT0EEC0N445PW07","writing-skills","How to write SKILL.md files that trigger reliably and teach effectively. Use when creating, improving, or reviewing Claude Code skills.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fxiaolai\u002Fnlpm\u002Fskills\u002Fnlpm\u002Fwriting-skills\u002FSKILL.md",[178,179,180,181],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},{"categoryNo":134,"categoryName":135,"taxonomyType":26,"taxonomyTypeDesc":27},[183,94,184,185,186,187,123,42,32,188,189,190,191],"writing skills","how","teach","write skill","write","claude code skills","files","how to","trigger",{"skillNo":193,"name":194,"nameZh":6,"description":195,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":196,"categories":197,"keywords":200,"publishedAt":49},"01M70P0SJFR4YVJQBGMHKGSKXT","writing-rules","How to write .claude\u002Frules\u002F files that Claude actually follows. Use when creating, improving, or reviewing project rules.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fxiaolai\u002Fnlpm\u002Fskills\u002Fnlpm\u002Fwriting-rules\u002FSKILL.md",[198,199],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":134,"categoryName":135,"taxonomyType":26,"taxonomyTypeDesc":27},[201,94,202,111,203,189,42,184,187,32,190],"Rules","writing rules","project rules"]