contract-validation

git-tao's avatarfrom git-tao

Validates frontend-backend API contracts. Apply when modifying API endpoints or service files.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 9, 2026

When & Why to Use This Skill

This Claude skill automates the validation of frontend-backend API contracts, ensuring that data schemas, endpoint routes, and naming conventions remain perfectly synchronized to prevent integration bugs and runtime errors.

Use Cases

  • Synchronizing backend Pydantic models with frontend TypeScript interfaces during API endpoint modifications.
  • Verifying the existence and correctness of backend routes when adding new service calls in the frontend.
  • Detecting and resolving naming convention mismatches, such as Python's snake_case versus TypeScript's camelCase.
  • Ensuring field optionality and enum value consistency across the full stack to maintain type safety.
  • Auditing existing codebases to ensure all API calls utilize a centralized API client rather than direct fetch/axios calls.
namecontract-validation
description"Validates frontend-backend API contracts. Apply when modifying API endpoints or service files."

Contract Validation Skill

Ensures frontend and backend API contracts remain synchronized.

When to Apply

  • Modifying API endpoints (backend)
  • Modifying service/API calls (frontend)
  • Adding new endpoints
  • Changing request/response schemas

Core Rules

1. Schema Consistency

Backend response MUST match frontend TypeScript interface:

# Backend (Python/FastAPI)
class UserResponse(BaseModel):
    user_id: str
    email: str
    created_at: datetime
// Frontend (TypeScript)
interface UserResponse {
    user_id: string;      // str -> string
    email: string;
    created_at: string;   // datetime -> ISO string
}

2. Endpoint Existence

Every frontend API call needs a backend endpoint:

// Frontend
export const getUser = (id: string) => api.get(`/users/${id}`);
# Backend MUST have:
@router.get("/users/{user_id}")
async def get_user(user_id: str) -> UserResponse:
    ...

3. Use Centralized API Client

// CORRECT
import api from '../utils/api';
const response = await api.get('/users/123');

// WRONG - direct axios/fetch
import axios from 'axios';
const response = await axios.get('http://localhost:8000/api/users/123');

Common Mismatches

Snake Case vs Camel Case

# Backend returns
{"user_id": "123", "created_at": "2025-01-01"}
// Frontend expects - MISMATCH!
interface User {
    userId: string;     // Wrong: should be user_id
    createdAt: string;  // Wrong: should be created_at
}

Optional vs Required

# Backend - field is optional
class Response(BaseModel):
    data: Optional[str] = None
// Frontend - assumes required - BUG!
interface Response {
    data: string;  // Should be: data?: string
}

Enum Mismatches

# Backend: lowercase
class Status(str, Enum):
    PENDING = "pending"
// Frontend: uppercase - WRONG
type Status = "PENDING";  // Should be "pending"

Verification Commands

# Find backend routes
grep -rn "@router\." backend/ --include="*.py"
grep -rn "router\.\(get\|post\)" backend/ --include="*.ts"

# Find frontend API calls
grep -rn "api\.\(get\|post\)" src/ --include="*.ts"

Checklist

  • Backend endpoint exists for frontend call
  • HTTP methods match
  • Field names match (snake_case)
  • Field types match
  • Optional fields marked with ?
  • Enum values match exactly