api-version
About
This skill manages API versioning for Hono routes in `apps/api/src/v1/`, helping developers create new API versions and migrate endpoints between versions. It assists with deprecating old endpoints, planning breaking changes, and maintaining backward compatibility. Use it when working with versioned API routes and preparing for future API releases.
Documentation
API Versioning Skill
This skill helps you manage API versions in apps/api/src/v1/ and prepare for future versions.
When to Use This Skill
- Creating a new API version (v2, v3, etc.)
- Deprecating old API endpoints
- Migrating endpoints between versions
- Planning breaking changes
- Maintaining backward compatibility
Current API Structure
apps/api/src/
├── v1/ # Current API version
│ ├── routes/
│ │ ├── cars.ts # Car registration endpoints
│ │ ├── coe.ts # COE bidding endpoints
│ │ ├── pqp.ts # PQP data endpoints
│ │ └── health.ts # Health check
│ └── index.ts # v1 router assembly
└── index.ts # Main Hono app with versioned routes
Versioning Strategy
URL-Based Versioning
The project uses URL path versioning:
https://api.sgcarstrends.com/v1/carshttps://api.sgcarstrends.com/v1/coe- Future:
https://api.sgcarstrends.com/v2/cars
Benefits
- Clear, explicit versioning visible in URLs
- Easy to cache and monitor per version
- Clients can migrate at their own pace
- Multiple versions can coexist
Creating a New API Version
Step 1: Create Version Directory
mkdir -p apps/api/src/v2/routes
Step 2: Copy Existing Routes
Start with current v1 routes as a base:
cp -r apps/api/src/v1/routes/* apps/api/src/v2/routes/
Step 3: Create Version Router
Create apps/api/src/v2/index.ts:
import { Hono } from "hono";
import { carsRouter } from "./routes/cars";
import { coeRouter } from "./routes/coe";
import { pqpRouter } from "./routes/pqp";
const v2 = new Hono();
// Mount routes
v2.route("/cars", carsRouter);
v2.route("/coe", coeRouter);
v2.route("/pqp", pqpRouter);
export default v2;
Step 4: Mount in Main App
Update apps/api/src/index.ts:
import { Hono } from "hono";
import v1 from "./v1";
import v2 from "./v2";
const app = new Hono();
// Mount API versions
app.route("/v1", v1);
app.route("/v2", v2); // Add new version
// Default to latest stable version
app.route("/", v1); // Keep v1 as default or change to v2 when stable
export default app;
Step 5: Implement Breaking Changes
Make necessary changes in v2 routes:
// v1 response format
{
"success": true,
"data": [...],
"count": 10
}
// v2 response format (breaking change)
{
"data": [...],
"meta": {
"total": 10,
"page": 1,
"pageSize": 10
}
}
Migration Patterns
1. Gradual Migration
Keep both versions running:
// v1/routes/cars.ts - deprecated but maintained
export const carsRouter = new Hono();
carsRouter.get("/", async (c) => {
// Old logic
return c.json({
success: true,
data: await getCars(),
});
});
// v2/routes/cars.ts - new implementation
export const carsRouter = new Hono();
carsRouter.get("/", async (c) => {
// New logic with pagination
const { page = 1, limit = 10 } = c.req.query();
const result = await getCars({ page, limit });
return c.json({
data: result.items,
meta: {
total: result.total,
page,
pageSize: limit,
},
});
});
2. Feature Flag Pattern
Use feature flags to test changes:
import { Hono } from "hono";
export const carsRouter = new Hono();
carsRouter.get("/", async (c) => {
const useV2Format = c.req.header("X-API-Version") === "2";
const data = await getCars();
if (useV2Format) {
return c.json({ data, meta: { ... } });
}
// v1 format
return c.json({ success: true, data });
});
3. Deprecation Warnings
Add deprecation headers to v1:
import { Hono } from "hono";
export const carsRouter = new Hono();
// Add deprecation middleware
carsRouter.use("*", async (c, next) => {
await next();
c.header("X-API-Deprecation", "true");
c.header("X-API-Sunset", "2025-12-31");
c.header("Link", '<https://api.sgcarstrends.com/v2/cars>; rel="successor-version"');
});
carsRouter.get("/", async (c) => {
// Existing logic
});
Breaking Changes Checklist
When introducing breaking changes, consider:
- Response structure changes
- Required parameter additions
- Authentication method changes
- URL structure modifications
- HTTP method changes
- Header requirement changes
- Error format modifications
- Data type changes
Version Documentation
Document versions in OpenAPI/Swagger:
// apps/api/src/v2/openapi.ts
import { OpenAPIHono } from "@hono/zod-openapi";
const app = new OpenAPIHono();
app.openapi(
{
method: "get",
path: "/cars",
summary: "Get car registrations (v2)",
deprecated: false,
tags: ["Cars"],
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: carResponseSchema,
},
},
},
},
},
async (c) => {
// Handler
}
);
Version Sunset Process
1. Announce Deprecation
- Update documentation
- Add deprecation headers
- Notify API consumers
- Set sunset date
2. Monitor Usage
Track v1 usage metrics:
import { middleware } from "hono/middleware";
v1.use("*", async (c, next) => {
// Log usage for monitoring
console.log("v1 API usage:", {
path: c.req.path,
user: c.get("user")?.id,
timestamp: new Date(),
});
await next();
});
3. Provide Migration Guide
Create migration documentation:
# Migrating from v1 to v2
## Breaking Changes
### Response Format
**v1:**
\`\`\`json
{ "success": true, "data": [...] }
\`\`\`
**v2:**
\`\`\`json
{ "data": [...], "meta": { ... } }
\`\`\`
### Pagination
v2 includes built-in pagination:
- Query params: `?page=1&limit=10`
- Response includes `meta` with pagination info
## Migration Steps
1. Update base URL from `/v1` to `/v2`
2. Update response parsing to handle new format
3. Add pagination parameters if needed
4. Update error handling for new error format
4. Remove Old Version
After sunset date:
# Remove v1 directory
rm -rf apps/api/src/v1
# Update main app
# Remove v1 mounting from apps/api/src/index.ts
Testing Multiple Versions
Test all active versions:
# Test v1
curl https://api.sgcarstrends.com/v1/cars
# Test v2
curl https://api.sgcarstrends.com/v2/cars
# Run version-specific tests
pnpm -F @sgcarstrends/api test -- src/v1
pnpm -F @sgcarstrends/api test -- src/v2
Deployment Considerations
Zero-Downtime Deployment
- Deploy v2 alongside v1
- Test v2 in production
- Gradually route traffic to v2
- Monitor error rates
- Rollback if issues occur
Environment Variables
Version-specific config:
# v1 settings
V1_RATE_LIMIT=100
V1_CACHE_TTL=300
# v2 settings
V2_RATE_LIMIT=200
V2_CACHE_TTL=600
Common Scenarios
Scenario 1: Add Required Parameter
v1: Optional parameter
carsRouter.get("/", async (c) => {
const make = c.req.query("make"); // optional
return c.json(await getCars({ make }));
});
v2: Required parameter (breaking change)
carsRouter.get("/", async (c) => {
const make = c.req.query("make");
if (!make) {
return c.json({ error: "make parameter required" }, 400);
}
return c.json(await getCars({ make }));
});
Scenario 2: Change Data Format
v1: Flat structure
{ id: 1, make: "Toyota", model: "Camry" }
v2: Nested structure (breaking change)
{
id: 1,
vehicle: {
make: "Toyota",
model: "Camry"
}
}
Scenario 3: Rename Endpoint
v1: /cars/list
v2: /cars (breaking change - URL structure)
Solution: Redirect in v1
v1.get("/cars/list", async (c) => {
c.header("X-API-Deprecated", "true");
c.header("Location", "/v2/cars");
return c.redirect("/v2/cars", 301);
});
References
- Hono documentation: Use Context7 for latest docs
- Related files:
apps/api/src/v1/- Current API versionapps/api/src/index.ts- Main app with version mountingapps/api/CLAUDE.md- API service documentation
Best Practices
- Semantic Versioning: Use v1, v2, v3 (not v1.1, v1.2)
- Backward Compatibility: Maintain old versions during migration period
- Documentation: Document all breaking changes clearly
- Communication: Announce deprecations well in advance
- Monitoring: Track usage of deprecated endpoints
- Testing: Maintain tests for all active versions
- Graceful Sunset: Provide sufficient migration time (6-12 months)
- Error Messages: Help users migrate with clear error messages
Quick Install
/plugin add https://github.com/sgcarstrends/sgcarstrends/tree/main/api-versionCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
evaluating-llms-harness
TestingThis Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
huggingface-accelerate
DevelopmentHuggingFace Accelerate provides the simplest API for adding distributed training to PyTorch scripts with just 4 lines of code. It offers a unified interface for multiple distributed training frameworks like DeepSpeed, FSDP, and DDP while handling automatic device placement and mixed precision. This makes it ideal for developers who want to quickly scale their PyTorch training across multiple GPUs or nodes without complex configuration.
nestjs
MetaThis skill provides NestJS development standards and architectural patterns for building domain-centric applications. It covers modular design, dependency injection, decorator patterns, and key framework features like controllers, services, middleware, and interceptors. Use it when developing NestJS applications, implementing APIs, configuring microservices, or integrating with databases.
