api-framework-fastify
Fastifyという高速なフレームワークを使って、JSON Schemaでデータの形式をチェックし、プラグインで機能を拡張、TypeScriptで型を安全に扱えるようにして、効率的なAPI開発を支援するSkill。
📜 元の英語説明(参考)
Fastify routes, JSON Schema validation, plugin system, TypeScript type providers
🇯🇵 日本人クリエイター向け解説
Fastifyという高速なフレームワークを使って、JSON Schemaでデータの形式をチェックし、プラグインで機能を拡張、TypeScriptで型を安全に扱えるようにして、効率的なAPI開発を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o api-framework-fastify.zip https://jpskill.com/download/10243.zip && unzip -o api-framework-fastify.zip && rm api-framework-fastify.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10243.zip -OutFile "$d\api-framework-fastify.zip"; Expand-Archive "$d\api-framework-fastify.zip" -DestinationPath $d -Force; ri "$d\api-framework-fastify.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
api-framework-fastify.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
api-framework-fastifyフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Fastify を用いた API 開発
クイックガイド: Fastify を使用して、組み込みの JSON Schema バリデーションと強力なプラグインカプセル化を備えた、高性能な Node.js REST API を構築します。エンドツーエンドの型安全性を実現するには、
@fastify/type-provider-typeboxを使用します(TypeとTypeBoxTypeProviderの両方がそこから再エクスポートされます)。共有プラグインをfastify-pluginでラップして、デコレータを公開します。シリアライゼーションのパフォーマンスとデータ漏洩防止のために、常にレスポンススキーマを定義してください。
<critical_requirements>
重要: この Skill を使用する前に
すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case, 名前付きエクスポート, インポート順序,
import type, 名前付き定数)
(型安全なリクエスト/レスポンス処理には、必ず withTypeProvider<>() を使用してください)
(親スコープにデコレータを公開するには、必ず共有プラグインを fastify-plugin でラップしてください)
(fast-json-stringify の最適化を有効にするには、必ずレスポンススキーマを定義してください)
(HTTP ステータスコードには、必ず名前付き定数を使用してください - 生の数値は絶対に使用しないでください)
</critical_requirements>
自動検出: Fastify, fastify.register, fastify.decorate, fastify-plugin, TypeBox, @fastify/type-provider-typebox, @fastify/type-provider-json-schema-to-ts, fastify-type-provider-zod, preHandler, onRequest, preSerialization, JSON Schema validation, fast-json-stringify, FastifyPluginAsyncTypebox
使用する場合:
- 高性能な REST API を構築する場合 (45k+ req/sec のベンチマーク)
- 自動的な型強制によるスキーマベースのバリデーションが必要な場合
- モジュール化されたアーキテクチャのためにプラグインのカプセル化が必要な場合
- クロス・カッティングな関心事のためにライフサイクル・フックが必要な場合
- 厳格な TypeScript の型安全性の要件を持つ API を構築する場合
使用しない場合:
- パフォーマンス要件のない単純な内部 API (既存のソリューションを検討してください)
- GraphQL API (専用の GraphQL サーバーを使用してください)
- サイズ制約のあるエッジ/サーバーレス (Fastify は最小限のフレームワークよりもフットプリントが大きいです)
- Express とのミドルウェアエコシステムの互換性が必要な場合
カバーされる主要なパターン:
- TypeScript 型プロバイダーによるサーバー設定
- プラグインシステムとカプセル化パターン
- リクエスト/レスポンスのための JSON Schema バリデーション
- ライフサイクル・フック (onRequest, preHandler, onSend など)
- Fastify/Request/Reply を拡張するためのデコレータ
- setErrorHandler によるエラー処理
- プレフィックスパターンによるルート構成
詳細なリソース:
- examples/core.md - サーバー設定、ルート、スキーマ、エラー処理、テスト
- examples/plugins.md - プラグインシステム、カプセル化、デコレータ
- examples/schemas.md - TypeBox スキーマ、バリデーション、型安全なルート
- examples/hooks.md - ライフサイクル・フックとクロス・カッティングな関心事
- reference.md - 意思決定フレームワーク、アンチパターン、クイックリファレンス
<philosophy>
哲学
スキーマファースト、コンパイルされたバリデーション。 Fastify は起動時に JSON スキーマを高度に最適化されたバリデーター関数にコンパイルします。これにより、単一の信頼できる情報源からランタイムの安全性とドキュメントの両方が提供されます。
プラグインのカプセル化は、モノリスにマイクロサービスを作成します。 各プラグインは、デコレータとフックのための独自のスコープを持ちます。子プラグインは親から継承しますが、親は子リソースにアクセスできません。これにより、関心の分離が明確になります。
犠牲のないパフォーマンス。 Fastify は、TypeScript の統合と包括的なフックシステムを通じて開発者の人間工学を維持しながら、Express よりも 2〜3 倍のスループットを実現します。
</philosophy>
<patterns>
コアパターン
パターン 1: 型プロバイダーによるサーバー設定
コンパイル時と実行時の型安全性のために、TypeBox で Fastify を設定します。Type は @fastify/type-provider-typebox から再エクスポートされます。
import Fastify from "fastify";
import { Type, TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
const SERVER_PORT = 3000;
const SERVER_HOST = "0.0.0.0";
const buildServer = () => {
const server = Fastify({
logger: { level: process.env.LOG_LEVEL ?? "info" },
}).withTypeProvider<TypeBoxTypeProvider>();
server.setErrorHandler(errorHandler);
server.register(userRoutes, { prefix: "/api/users" });
return server;
};
export { buildServer };
利点: TypeBox プロバイダーはスキーマからの型推論を可能にし、ファクトリ関数はテストを可能にし、Type は同じパッケージからインポートされます。
起動、エラー処理、およびテストを含む完全な例: examples/core.md
パターン 2: TypeBox によるスキーマ定義
TypeScript の型とランタイムのバリデーションの両方を提供するスキーマを単一の情報源から定義します。
import { Type, Static } from "@fastify/type-provider-typebox";
const MIN_USERNAME_LENGTH = 3;
const MAX_USERNAME_LENGTH = 50;
export const UserSchema = Type.Object({
id: Type.String({ format: "uuid" }),
username: Type.String({
minLength: MIN_USERNAME_LENGTH,
maxLength: MAX_USERNAME_LENGTH,
}),
email: Type.String({ format: "email" }),
});
// スキーマから TypeScript の型を派生させる
export type User = Static<typeof UserSchema>;
利点: 型とバリデーションのための単一の情報源、Static<> は TS 型を自動的に派生させます。
完全なスキーマパターン (構成、部分的な更新、再利用可能なコンポーネント): examples/schemas.md
パターン 3: 完全なスキーマによるルート定義
完全な型安全性とシリアライゼーションの最適化のために、リクエストとレスポンスのスキーマを持つルートを定義します。
import type { FastifyPluginAsync } from "fastify";
import { Type } from "@fastify/type-provider-typebox";
const HTTP_OK = 200;
const HTTP_NOT_FOUND = 404;
export const userRoutes: FastifyPluginAsync = async (fastify) => {
fastify.get(
"/:id",
{
schema: {
params: UserParamsSchema,
response: {
[HTTP_OK]: UserSchema,
[HTTP_NOT_FOUND]: ErrorSchema,
},
},
},
async (request, reply) => {
const user = await fastify.userService.findById(request.params.id);
if (!user) {
return reply.status(HTTP
(原文がここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
API Development with Fastify
Quick Guide: Use Fastify for high-performance Node.js REST APIs with built-in JSON Schema validation and powerful plugin encapsulation. Use
@fastify/type-provider-typeboxfor end-to-end type safety (bothTypeandTypeBoxTypeProviderre-exported from it). Wrap shared plugins withfastify-pluginto expose decorators. Always define response schemas for serialization performance and data leak prevention.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use withTypeProvider<>() for type-safe request/response handling)
(You MUST wrap shared plugins with fastify-plugin to expose decorators to parent scope)
(You MUST define response schemas to enable fast-json-stringify optimization)
(You MUST use named constants for HTTP status codes - never raw numbers)
</critical_requirements>
Auto-detection: Fastify, fastify.register, fastify.decorate, fastify-plugin, TypeBox, @fastify/type-provider-typebox, @fastify/type-provider-json-schema-to-ts, fastify-type-provider-zod, preHandler, onRequest, preSerialization, JSON Schema validation, fast-json-stringify, FastifyPluginAsyncTypebox
When to use:
- Building high-performance REST APIs (45k+ req/sec benchmarks)
- Need schema-based validation with automatic coercion
- Want plugin encapsulation for modular architecture
- Require lifecycle hooks for cross-cutting concerns
- Building APIs with strict TypeScript type safety requirements
When NOT to use:
- Simple internal APIs without performance requirements (consider your existing solution)
- GraphQL APIs (use dedicated GraphQL servers)
- Edge/serverless with size constraints (Fastify has larger footprint than minimal frameworks)
- When middleware ecosystem compatibility with Express is required
Key patterns covered:
- Server setup with TypeScript type providers
- Plugin system and encapsulation patterns
- JSON Schema validation for request/response
- Lifecycle hooks (onRequest, preHandler, onSend, etc.)
- Decorators for extending Fastify/Request/Reply
- Error handling with setErrorHandler
- Route organization with prefix patterns
Detailed Resources:
- examples/core.md - Server setup, routes, schemas, error handling, testing
- examples/plugins.md - Plugin system, encapsulation, decorators
- examples/schemas.md - TypeBox schemas, validation, type-safe routes
- examples/hooks.md - Lifecycle hooks and cross-cutting concerns
- reference.md - Decision frameworks, anti-patterns, quick reference
<philosophy>
Philosophy
Schema-first, compiled validation. Fastify compiles JSON schemas at startup into highly optimized validator functions. This provides both runtime safety and documentation from a single source of truth.
Plugin encapsulation creates microservices in a monolith. Each plugin has its own scope for decorators and hooks. Child plugins inherit from parents, but parents cannot access child resources - enabling clean separation of concerns.
Performance without sacrifice. Fastify achieves 2-3x throughput over Express while maintaining developer ergonomics through TypeScript integration and comprehensive hook system.
</philosophy>
<patterns>
Core Patterns
Pattern 1: Server Setup with Type Provider
Configure Fastify with TypeBox for compile-time AND runtime type safety. Type is re-exported from @fastify/type-provider-typebox.
import Fastify from "fastify";
import { Type, TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
const SERVER_PORT = 3000;
const SERVER_HOST = "0.0.0.0";
const buildServer = () => {
const server = Fastify({
logger: { level: process.env.LOG_LEVEL ?? "info" },
}).withTypeProvider<TypeBoxTypeProvider>();
server.setErrorHandler(errorHandler);
server.register(userRoutes, { prefix: "/api/users" });
return server;
};
export { buildServer };
Why good: TypeBox provider enables type inference from schemas, factory function enables testing, Type imported from same package
Full example with startup, error handling, and testing: examples/core.md
Pattern 2: Schema Definition with TypeBox
Define schemas that provide both TypeScript types AND runtime validation from a single source.
import { Type, Static } from "@fastify/type-provider-typebox";
const MIN_USERNAME_LENGTH = 3;
const MAX_USERNAME_LENGTH = 50;
export const UserSchema = Type.Object({
id: Type.String({ format: "uuid" }),
username: Type.String({
minLength: MIN_USERNAME_LENGTH,
maxLength: MAX_USERNAME_LENGTH,
}),
email: Type.String({ format: "email" }),
});
// Derive TypeScript types from schemas
export type User = Static<typeof UserSchema>;
Why good: Single source of truth for types and validation, Static<> derives TS types automatically
Full schema patterns (composition, partial updates, reusable components): examples/schemas.md
Pattern 3: Route Definition with Full Schema
Define routes with request AND response schemas for complete type safety and serialization optimization.
import type { FastifyPluginAsync } from "fastify";
import { Type } from "@fastify/type-provider-typebox";
const HTTP_OK = 200;
const HTTP_NOT_FOUND = 404;
export const userRoutes: FastifyPluginAsync = async (fastify) => {
fastify.get(
"/:id",
{
schema: {
params: UserParamsSchema,
response: {
[HTTP_OK]: UserSchema,
[HTTP_NOT_FOUND]: ErrorSchema,
},
},
},
async (request, reply) => {
const user = await fastify.userService.findById(request.params.id);
if (!user) {
return reply.status(HTTP_NOT_FOUND).send({
statusCode: HTTP_NOT_FOUND,
error: "Not Found",
message: `User ${request.params.id} not found`,
});
}
return reply.status(HTTP_OK).send(user);
},
);
};
Why good: Response schemas enable fast-json-stringify (2-3x faster), full type inference on request objects, HTTP constants prevent magic numbers
Complete CRUD routes with pagination: examples/core.md
Pattern 4: Plugin Encapsulation
Default plugins are encapsulated - decorators stay within scope. Use fastify-plugin (fp) to break encapsulation for shared infrastructure.
// ENCAPSULATED - decorators only available within this plugin
export const authRoutes: FastifyPluginAsync = async (fastify) => {
fastify.decorate("authConfig", { tokenExpiry: 3600 });
// authConfig only accessible in this plugin
};
// SHARED - decorators exposed to parent scope
import fp from "fastify-plugin";
declare module "fastify" {
interface FastifyInstance {
config: AppConfig;
}
}
const configPlugin: FastifyPluginAsync = async (fastify) => {
fastify.decorate("config", { apiVersion: "v1" });
};
export const appConfig = fp(configPlugin, {
name: "app-config",
dependencies: [],
});
Why good: Domain plugins stay isolated, shared utilities use fp() to expose decorators, TypeScript augmentation provides type safety
Full plugin examples with dependencies, registration order: examples/plugins.md
Pattern 5: Lifecycle Hooks
Use hooks for cross-cutting concerns at specific lifecycle points.
Hook execution order:
onRequest- Before parsing (request ID, timing)preParsing- Transform request streampreValidation- Before schema validationpreHandler- After validation (auth, authorization)preSerialization- Transform response objectonSend- Final payload modificationonResponse- After response sent (metrics, logging)onError- On error (error logging)
// Plugin-level: applies to ALL routes in this plugin
fastify.addHook("preHandler", requireAuth);
// Route-level: applies to single route
fastify.delete(
"/users/:id",
{
preHandler: [requireAuth, requireAdmin],
},
async (request) => {
/* ... */
},
);
Why good: Plugin-level for consistent protection, route-level for selective application, hooks execute in array order
Full hook examples (request timing, auth, response headers, error logging): examples/hooks.md
Pattern 6: Error Handling
Implement centralized error handling with setErrorHandler. Fastify validation errors have a .validation array (not .message).
import type { FastifyError, FastifyReply, FastifyRequest } from "fastify";
const HTTP_BAD_REQUEST = 400;
const HTTP_INTERNAL_ERROR = 500;
export const errorHandler = (
error: FastifyError,
request: FastifyRequest,
reply: FastifyReply,
) => {
if (error.validation) {
return reply.status(HTTP_BAD_REQUEST).send({
statusCode: HTTP_BAD_REQUEST,
error: "Bad Request",
message: "Validation failed",
details: error.validation,
});
}
request.log.error(
{ error: error.message, stack: error.stack },
"Unexpected error",
);
return reply.status(HTTP_INTERNAL_ERROR).send({
statusCode: HTTP_INTERNAL_ERROR,
error: "Internal Server Error",
message: "An unexpected error occurred",
});
};
Why good: Validation errors expose details, unexpected errors logged with stack but hidden from client
Full error handler with custom error classes: examples/core.md
Pattern 7: Decorators
Extend Fastify instance, Request, and Reply with decorators.
// Instance decorator - services/utilities
fastify.decorate("myService", serviceInstance);
// Request decorator - per-request state (initialize with null, set in hook)
fastify.decorateRequest("userId", null);
fastify.addHook("preHandler", async (request) => {
request.userId = decoded.userId;
});
// Reply decorator - response helpers (use function for `this` binding)
fastify.decorateReply(
"notFound",
function (this: FastifyReply, message: string) {
this.status(HTTP_NOT_FOUND).send({
statusCode: HTTP_NOT_FOUND,
error: "Not Found",
message,
});
},
);
CRITICAL: Never use reference types (objects, arrays) as initial decorator values - they are shared across ALL requests. Use null and set per-request in hooks.
Full decorator examples: examples/plugins.md
Pattern 8: Testing with server.inject()
Use the factory pattern for test isolation and server.inject() for zero-network-overhead testing.
import { buildServer } from "./server";
let server: ReturnType<typeof buildServer>;
beforeEach(async () => {
server = buildServer();
await server.ready();
});
afterEach(async () => {
await server.close();
});
it("should list users", async () => {
const response = await server.inject({
method: "GET",
url: "/api/users",
query: { limit: "10" },
});
expect(response.statusCode).toBe(200);
expect(response.json()).toHaveProperty("users");
});
Why good: server.inject() tests without network, beforeEach/afterEach ensures clean state, tests validation and success paths
</patterns>
<red_flags>
RED FLAGS
High Priority Issues
- No type provider configured - Loses compile-time type safety on request/response
- Shared plugins without
fastify-plugin- Decorators invisible to other plugins - Missing response schemas - Loses 2-3x serialization performance AND risks data leaks
- Raw status code numbers - Use named constants (
HTTP_OK,HTTP_NOT_FOUND) - Reference types in
decorateRequest/decorateReply- Shared mutable state across ALL requests (security risk)
Medium Priority Issues
- No error handler configured - Stack traces exposed to clients in production
- Missing
dependenciesin plugin options - Race conditions on decorator access - No schema for query/params - No validation, types are
unknown - Inline route handlers in god files - Use modular route plugins with prefix
Common Mistakes
- Forgetting
await server.ready()- Plugins may not be fully loaded - Not cleaning up in
onClose- Connection leaks on shutdown - Mixing async/await with
donecallback - Pick one pattern per hook (causes double-completion) - Using Express patterns -
res.send()vsreply.send(),next()vs returning
Gotchas & Edge Cases
- Hook return values: Returning a value from hooks sends response immediately (short-circuits)
- Plugin registration order: Later plugins can't access earlier encapsulated decorators
- Validation error shape: Fastify validation errors have
.validationarray, not.message - Route specificity: More specific routes must be registered before wildcards
- preHandler order: Route-level runs AFTER plugin-level hooks
- onResponse timing: Runs after response sent, cannot modify response
- Schema compilation: Happens at startup, errors surface during
server.ready() - v5 redirect order:
reply.redirect(url, statusCode)notreply.redirect(statusCode, url)(reversed from v4) - v5 reply.sent: Use
reply.hijack()instead of settingreply.sent = true
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md
(You MUST use withTypeProvider<>() for type-safe request/response handling)
(You MUST wrap shared plugins with fastify-plugin to expose decorators to parent scope)
(You MUST define response schemas to enable fast-json-stringify optimization)
(You MUST use named constants for HTTP status codes - never raw numbers)
Failure to follow these rules will break type safety and lose performance benefits.
</critical_reminders>