api-design について
api-designは、REST、GraphQL、tRPCなどのHTTPエンドポイントを設計・実装する開発者向けスキルです。既存の規約の調査から入力検証、API文書化、型の同期、契約チェックまでを扱います。
主な機能
- 01既存ルートと規約を把握
- 02入力検証とエラーレスポンスを設計
- 03REST・GraphQL・tRPCのエンドポイントを実装
- 04OpenAPI文書を生成
- 05フロントエンドとバックエンドの型を同期
- 06API契約を検証
活用シーン
- 01APIエンドポイントやルートを作成
- 02リクエスト検証やミドルウェアを追加
- 03API文書を生成
- 04RESTからtRPCなどへ移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mgd34msu/ goodvibes-plugin --skill api-designインストール後、Claude Code で/api-designを入力して読み込まれたか確認します。
同梱ファイルreferences/api-style-guide.mdscripts/api-checklist.sh
詳細
リソース
scripts/
api-checklist.sh
references/
api-style-guide.md
API 設計
このスキルでは、GoodVibes の精度とプロジェクトエンジンツールを使用して、API エンドポイントを設計し実装する方法を説明します。REST API、GraphQL リゾルバー、tRPC プロシージャ、またはあらゆる HTTP エンドポイントを構築する際に、このワークフローを使用してください。
このスキルを使用するタイミング
以下の場合にこのスキルを読み込んでください。
- 新しい API エンドポイントまたはルートを構築するとき
- リクエストの検証またはミドルウェアを実装するとき
- エラーレスポンス形式を設計するとき
- API ドキュメントを生成するとき
- フロントエンドとバックエンドの型を同期するとき
- API パラダイム間(REST から tRPC など)を移行するとき
トリガーフレーズ:「create an API」、「build endpoint」、「implement route」、「add validation」、「GraphQL resolver」、「tRPC procedure」。
コアワークフロー
フェーズ 1:調査
実装を始める前に、既存のパターンを把握してください。
ステップ 1.1:既存のルートを把握する
get_api_routes を使用して、プロジェクト内のすべての API エンドポイントを確認します。
mcp__plugin_goodvibes_project-engine__get_api_routes:
project_root: "." # or specific path
確認できる内容:
- ルートファイルの場所と命名規則
- 使用中の HTTP メソッド(GET、POST、PUT、DELETE、PATCH)
- ルート構造(フラットかネストか)
- フレームワークのパターン(Next.js App Router、Express、Fastify、tRPC)
ステップ 1.2:パターンを見つける
discover を使用して、ミドルウェア、検証、エラー処理、認証のパターンを見つけます。
discover:
queries:
- id: middleware
type: grep
pattern: "(middleware|use\\()"
glob: "**/*.{ts,js}"
- id: validation
type: grep
pattern: "(z\\.|yup\\.|joi\\.|validator\\.)"
glob: "**/*.{ts,js}"
- id: error_handlers
type: grep
pattern: "(catch|try|Error|throw)"
glob: "src/api/**/*.{ts,js}"
- id: auth_patterns
type: grep
pattern: "(auth|jwt|session|bearer|getServerSession)"
glob: "**/*.{ts,js}"
verbosity: files_only
確認できる内容:
- 使用中の検証ライブラリ(Zod、Yup、Joi)
- エラー処理のパターン
- 認証ミドルウェア
- 既存のルート構造
ステップ 1.3:主要なファイルを読む
代表的なルートファイルを 2~3 個読み、実装パターンを把握します。
precision_read:
files:
- path: "src/api/users/route.ts" # or discovered route
extract: content
- path: "src/lib/validation.ts" # or discovered validation file
extract: outline
verbosity: standard
フェーズ 2:意思決定
ニーズに合った API パラダイムを選択します。詳しい判断ツリーについては、references/api-style-guide.md を参照してください。
クイック判断ガイド
REST、GraphQL、tRPC、Server Actions の判断ツリーについては、references/api-style-guide.md を確認してください。
フェーズ 3:実装
ステップ 3.1:検証スキーマを定義する
プロジェクトの検証ライブラリを使用して、リクエストの検証を作成します。
Zod を使用した例:
import { z } from 'zod';
export const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
role: z.enum(['user', 'admin']).default('user'),
});
export type CreateUserInput = z.infer<typeof createUserSchema>;
ベストプラクティス:
- すべての入力(body、query params、headers)を検証する
- 厳格なスキーマを使用する(未知のキーを許可しない)
- 明確なエラーメッセージを提示する
- 再利用できるよう、推論された型をエクスポートする
ステップ 3.2:ルートハンドラーを実装する
プロジェクトの規約に従って、ルートハンドラーを記述します。
Next.js App Router の例:
import { NextRequest, NextResponse } from 'next/server';
import { createUserSchema } from './schema';
import { db } from '@/lib/db';
import { getServerSession } from '@/lib/auth';
export async function POST(request: NextRequest) {
// 1. Authentication
const session = await getServerSession();
if (!session) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
// 2. Parse and validate input
const body = await request.json();
const result = createUserSchema.safeParse(body);
if (!result.success) {
return NextResponse.json(
{ error: 'Validation failed', details: result.error.flatten() },
{ status: 400 }
);
}
// 3. Authorization check
if (session.user.role !== 'admin') {
return NextResponse.json(
{ error: 'Forbidden' },
{ status: 403 }
);
}
// 4. Business logic
try {
const user = await db.user.create({
data: result.data,
});
return NextResponse.json(user, { status: 201 });
} catch (error) {
console.error('Failed to create user:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
tRPC の例:
import { z } from 'zod';
import { protectedProcedure, router } from '../trpc';
export const userRouter = router({
create: protectedProcedure
.input(
z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
})
)
.mutation(async ({ ctx, input }) => {
if (ctx.session.user.role !== 'admin') {
throw new TRPCError({ code: 'FORBIDDEN' });
}
return await ctx.db.user.create({
data: input,
});
}),
});
ステップ 3.3:精度ツールを使用して記述する
precision_write を使用して、ルートファイル、検証スキーマ、型を作成します。
precision_write:
files:
- path: "src/app/api/users/route.ts"
content: |
import { NextRequest, NextResponse } from 'next/server';
// ... [full handler implementation]
- path: "src/app/api/users/schema.ts"
content: |
import { z } from 'zod';
export const createUserSchema = z.object({ ... });
verbosity: count_only
フェーズ 4:エラー処理
標準エラーレスポンス形式
すべてのエンドポイントで一貫したエラーレスポンスを維持します。
interface APIError {
error: string; // Human-readable message
code?: string; // Machine-readable error code
details?: unknown; // Validation errors or additional context
trace_id?: string; // For debugging in production
}
HTTP ステータスコードのガイドライン:
200- 成功201- 作成済み(POST)204- コンテンツなし(DELETE)400- 不正なリクエスト(検証エラー)401- 認証されていない(未認証)403- 禁止(権限なし)404- 見つからない409- 競合(リソースが重複)500- 内部サーバーエラー
エラー処理パターン
try {
// Business logic
} catch (error) {
// Log for debugging (never expose to client)
console.error('Operation failed:', error);
// User-facing error
return NextResponse.json(
{ error: 'Failed to process request' },
{ status: 500 }
);
}
決して公開しないもの:
- 本番環境でのスタックトレース
- データベースのエラーメッセージ
- ファイルパスまたは内部構造
- シークレットまたは認証情報
フェーズ 5:ドキュメント作成
ステップ 5.1:OpenAPI 仕様を生成する
REST API の場合は、OpenAPI ドキュメントを自動生成します。
mcp__plugin_goodvibes_project-engine__generate_openapi:
project_root: "."
output_path: "docs/openapi.yaml"
生成される内容:
- ルートパスと HTTP メソッド
- リクエスト/レスポンスのスキーマ
- 認証要件
- リクエスト/レスポンスの例
ツールが存在しない場合、または失敗した場合は、エンドポイントを手動でドキュメント化します。
# In a routes.md file
POST /api/users
Description: Create a new user
Auth: Required (admin)
Body: { email: string, name: string, role?: 'user' | 'admin' }
Response 201: User object
Response 400: Validation error
Response 401: Unauthorized
Response 403: Forbidden
ステップ 5.2:JSDoc コメントを追加する
JSDoc を使用してルートハンドラーをドキュメント化します。
/**
* Create a new user.
*
* @requires Authentication (admin role)
* @body {CreateUserInput} User data
* @returns {User} Created user object
* @throws {401} Unauthorized - Not authenticated
* @throws {403} Forbidden - Not an admin
* @throws {400} Bad Request - Validation failed
*/
export async function POST(request: NextRequest) {
// ...
}
フェーズ 6:型安全性
ステップ 6.1:フロントエンド/バックエンドの型を同期する
sync_api_types を使用して、型の整合性を確認します。
mcp__plugin_goodvibes_project-engine__sync_api_types:
backend_dir: "src/app/api"
frontend_dir: "src/lib/api-client"
確認される内容:
- フロントエンドとバックエンドのリクエスト型が一致している
- レスポンス型に一貫性がある
- フィールド名や型に不一致がない
- すべてのエンドポイントに対応するクライアントコードがある
ステップ 6.2:API 型をエクスポートする
クライアントで使用できるように型を公開します。
// src/types/api.ts
export type { CreateUserInput, User } from '@/app/api/users/schema';
tRPC では、型が自動的に推論されます。
// Client code
import { trpc } from '@/lib/trpc';
const user = await trpc.user.create.mutate({
email: '[email protected]',
name: 'Test User',
}); // Fully typed!
フェーズ 7:検証
Step 7.1: API コントラクトを検証する
validate_api_contract を使用して、レスポンスが仕様に一致することを確認します。
mcp__plugin_goodvibes_analysis-engine__validate_api_contract:
spec_path: "docs/openapi.yaml"
implementation_dir: "src/app/api"
検証内容:
- レスポンスのスキーマが OpenAPI 仕様に一致していること
- ステータスコードが正しいこと
- 必須フィールドが含まれていること
- 型が正確であること
ツールが存在しない場合は、手動でテストします。
# Use curl or httpie to test endpoints
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","name":"Test"}'
Step 7.2: 型チェックを実行する
TypeScript のコンパイルを確認します。
precision_exec:
commands:
- cmd: "npm run typecheck"
expect:
exit_code: 0
stderr_empty: true
verbosity: minimal
Step 7.3: API チェックリストスクリプトを実行する
検証スクリプトを使用して、品質を確認します。
bash scripts/api-checklist.sh .
検証スイートの全容については、scripts/api-checklist.sh を参照してください。
ミドルウェアのパターン
references/api-style-guide.md のパターンに従って、認証、CORS、レート制限のミドルウェアを実装します。CORS のオリジンなど、セキュリティ上重要な設定には、必ず環境変数を使用してください。
テスト
成功ケース、バリデーションエラー、認証失敗を網羅する、意味のあるアサーションを用いて API エンドポイントをテストします。テストのパターンについては、references/api-style-guide.md を参照してください。
よくあるアンチパターン
避けること:
- クライアントからの入力を検証せずに信頼する
- データベースのエラーをクライアントに公開する
- 変更処理に GET を使用する
- エンドポイントごとに異なるレスポンス形式を返す
- 認証チェックを省略する
- 認可(リソースの所有権)を無視する
- ルートハンドラーで
any型を使用する - 機密情報(API キー、シークレット)をハードコードする
- エラーに対して 200 を返す
実施すること:
- 厳密なスキーマですべての入力を検証する
- 一貫したエラーレスポンス形式を使用する
- HTTP のセマンティクスに従う(GET = 読み取り、POST = 作成など)
- 適切な認証と認可を実装する
- すべての API コードで TypeScript を使用する
- 環境変数からシークレットを読み込む
- 適切なステータスコードを返す
- デバッグ用にエラーをログに記録する(公開はしない)
クイックリファレンス
調査フェーズ:
get_api_routes: { project_root: "." }
discover: { queries: [middleware, validation, auth], verbosity: files_only }
precision_read: { files: [route examples], extract: content }
実装フェーズ:
precision_write: { files: [route, schema, types], verbosity: count_only }
検証フェーズ:
generate_openapi: { project_root: ".", output_path: "docs/openapi.yaml" }
validate_api_contract: { spec_path: "docs/openapi.yaml" }
sync_api_types: { backend_dir: "src/api", frontend_dir: "src/lib" }
precision_exec: { commands: [{ cmd: "npm run typecheck" }] }
実装後:
bash scripts/api-checklist.sh .
詳細な判断ツリーとフレームワーク固有のパターンについては、references/api-style-guide.md を参照してください。