api-version

Manage API versioning strategy for Hono routes in apps/api/src/v1. Use when creating new API versions or migrating endpoints between versions.

16 stars

Best use case

api-version is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Manage API versioning strategy for Hono routes in apps/api/src/v1. Use when creating new API versions or migrating endpoints between versions.

Teams using api-version should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/api-version/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/backend/api-version/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/api-version/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How api-version Compares

Feature / Agentapi-versionStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Manage API versioning strategy for Hono routes in apps/api/src/v1. Use when creating new API versions or migrating endpoints between versions.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# 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/cars`
- `https://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

```bash
mkdir -p apps/api/src/v2/routes
```

### Step 2: Copy Existing Routes

Start with current v1 routes as a base:

```bash
cp -r apps/api/src/v1/routes/* apps/api/src/v2/routes/
```

### Step 3: Create Version Router

Create `apps/api/src/v2/index.ts`:

```typescript
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`:

```typescript
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:

```typescript
// 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:

```typescript
// 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:

```typescript
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:

```typescript
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:

```typescript
// 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:

```typescript
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:

```markdown
# 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:

```bash
# 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:

```bash
# 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

1. Deploy v2 alongside v1
2. Test v2 in production
3. Gradually route traffic to v2
4. Monitor error rates
5. Rollback if issues occur

### Environment Variables

Version-specific config:

```env
# 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
```typescript
carsRouter.get("/", async (c) => {
  const make = c.req.query("make"); // optional
  return c.json(await getCars({ make }));
});
```

**v2:** Required parameter (breaking change)
```typescript
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
```typescript
{ id: 1, make: "Toyota", model: "Camry" }
```

**v2:** Nested structure (breaking change)
```typescript
{
  id: 1,
  vehicle: {
    make: "Toyota",
    model: "Camry"
  }
}
```

### Scenario 3: Rename Endpoint

**v1:** `/cars/list`
**v2:** `/cars` (breaking change - URL structure)

Solution: Redirect in v1
```typescript
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 version
  - `apps/api/src/index.ts` - Main app with version mounting
  - `apps/api/CLAUDE.md` - API service documentation

## Best Practices

1. **Semantic Versioning**: Use v1, v2, v3 (not v1.1, v1.2)
2. **Backward Compatibility**: Maintain old versions during migration period
3. **Documentation**: Document all breaking changes clearly
4. **Communication**: Announce deprecations well in advance
5. **Monitoring**: Track usage of deprecated endpoints
6. **Testing**: Maintain tests for all active versions
7. **Graceful Sunset**: Provide sufficient migration time (6-12 months)
8. **Error Messages**: Help users migrate with clear error messages

Related Skills

version-control

16
from diegosouzapw/awesome-omni-skill

Manage Git repositories and collaborative workflows — branching strategies, commit hygiene, conflict resolution, pull requests, hooks, and .gitignore management.

version-control-rule

16
from diegosouzapw/awesome-omni-skill

Applies to git related files, specifies to always use git for version control.

symfony:api-platform-versioning

16
from diegosouzapw/awesome-omni-skill

Use when symfony api platform versioning

Conversion Optimization

16
from diegosouzapw/awesome-omni-skill

Conversion Rate Optimization (CRO) is the systematic process of increasing the percentage of website or app visitors who complete a desired action (conversion) through data-driven experimentation and

API Versioning

16
from diegosouzapw/awesome-omni-skill

Implement API versioning strategies for backward compatibility. Covers URL versioning, header versioning, and deprecation workflows.

api-versioning-deprecation-planner

16
from diegosouzapw/awesome-omni-skill

Plans safe API evolution with versioning strategies, client migration guides, deprecation timelines, and backward compatibility considerations. Use for "API versioning", "deprecation planning", "API evolution", or "breaking changes".

api-design-and-versioning

16
from diegosouzapw/awesome-omni-skill

Design REST/GraphQL APIs with versioning and deprecation strategy.

bgo

10
from diegosouzapw/awesome-omni-skill

Automates the complete Blender build-go workflow, from building and packaging your extension/add-on to removing old versions, installing, enabling, and launching Blender for quick testing and iteration.

Coding & Development

obsidian-daily

16
from diegosouzapw/awesome-omni-skill

Manage Obsidian Daily Notes via obsidian-cli. Create and open daily notes, append entries (journals, logs, tasks, links), read past notes by date, and search vault content. Handles relative dates like "yesterday", "last Friday", "3 days ago".

obsidian-additions

16
from diegosouzapw/awesome-omni-skill

Create supplementary materials attached to existing notes: experiments, meetings, reports, logs, conspectuses, practice sessions, annotations, AI outputs, links collections. Two-step process: (1) create aggregator space, (2) create concrete addition in base/additions/. INVOKE when user wants to attach any supplementary material to an existing note. Triggers: "addition", "create addition", "experiment", "meeting notes", "report", "conspectus", "log", "practice", "annotations", "links", "link collection", "аддишн", "конспект", "встреча", "отчёт", "эксперимент", "практика", "аннотации", "ссылки", "добавь к заметке".

observe

16
from diegosouzapw/awesome-omni-skill

Query and manage Observe using the Observe CLI. Use when the user wants to run OPAL queries, list datasets, manage objects, or interact with their Observe tenant from the command line.

observability-review

16
from diegosouzapw/awesome-omni-skill

AI agent that analyzes operational signals (metrics, logs, traces, alerts, SLO/SLI reports) from observability platforms (Prometheus, Datadog, New Relic, CloudWatch, Grafana, Elastic) and produces practical, risk-aware triage and recommendations. Use when reviewing system health, investigating performance issues, analyzing monitoring data, evaluating service reliability, or providing SRE analysis of operational metrics. Distinguishes between critical issues requiring action, items needing investigation, and informational observations requiring no action.