MCP HubMCP Hub
スキル一覧に戻る

Fastify

oriolrius
更新日 Today
107 閲覧
1
1
1
GitHubで表示
メタapidesign

について

このClaudeスキルは、Fastifyフレームワークを使用した高パフォーマンスなNode.js WebサーバーとREST APIの構築に関する専門的なガイダンスを提供します。サーバー設定、ルーティング、プラグイン、フック、バリデーション、エラーハンドリング、TypeScript統合を網羅しています。Fastifyのスキーマベースのバリデーション、プラグインアーキテクチャ、またはパフォーマンス最適化に関する支援が必要な際に、このスキルをご利用ください。

クイックインストール

Claude Code

推奨
プラグインコマンド推奨
/plugin add https://github.com/oriolrius/pki-manager-web
Git クローン代替
git clone https://github.com/oriolrius/pki-manager-web.git ~/.claude/skills/Fastify

このコマンドをClaude Codeにコピー&ペーストしてスキルをインストールします

ドキュメント

Fastify

Expert assistance with Fastify - Fast and low overhead web framework for Node.js.

Overview

Fastify is a highly performant web framework:

  • Fast: One of the fastest Node.js frameworks
  • Low Overhead: Minimal resource consumption
  • Schema-based: JSON Schema validation
  • TypeScript: Excellent TypeScript support
  • Plugin Architecture: Extensible with plugins
  • Logging: Built-in logging with Pino

Installation

npm install fastify
npm install --save-dev @types/node

# Common plugins
npm install @fastify/cors          # CORS support
npm install @fastify/websocket     # WebSocket support
npm install @fastify/cookie        # Cookie parsing
npm install @fastify/jwt           # JWT authentication
npm install @fastify/helmet        # Security headers
npm install @fastify/rate-limit    # Rate limiting

Quick Start

import Fastify from 'fastify';

const server = Fastify({
  logger: true, // Enable Pino logging
});

server.get('/ping', async (request, reply) => {
  return { pong: 'it worked!' };
});

await server.listen({ port: 3000, host: '0.0.0.0' });
console.log('Server listening on http://localhost:3000');

Server Configuration

import Fastify from 'fastify';

const server = Fastify({
  logger: {
    level: 'info',
    transport: {
      target: 'pino-pretty', // Pretty printing in development
    },
  },
  bodyLimit: 1048576, // 1MB body limit
  caseSensitive: true, // Case-sensitive routes
  ignoreTrailingSlash: false,
  requestIdHeader: 'x-request-id',
  requestIdLogLabel: 'reqId',
  trustProxy: true, // Trust proxy headers
});

Routing

Basic Routes

// GET
server.get('/users', async (request, reply) => {
  return [{ id: 1, name: 'John' }];
});

// POST
server.post('/users', async (request, reply) => {
  const { name, email } = request.body;
  return { id: 2, name, email };
});

// PUT
server.put('/users/:id', async (request, reply) => {
  const { id } = request.params;
  const { name } = request.body;
  return { id, name };
});

// DELETE
server.delete('/users/:id', async (request, reply) => {
  const { id } = request.params;
  return { deleted: id };
});

// PATCH
server.patch('/users/:id', async (request, reply) => {
  return { updated: true };
});

Route Parameters

// URL parameters
server.get<{
  Params: { id: string };
}>('/users/:id', async (request, reply) => {
  const { id } = request.params; // Typed!
  return { id };
});

// Multiple parameters
server.get<{
  Params: { userId: string; postId: string };
}>('/users/:userId/posts/:postId', async (request, reply) => {
  const { userId, postId } = request.params;
  return { userId, postId };
});

// Query parameters
server.get<{
  Querystring: { search?: string; limit?: number };
}>('/search', async (request, reply) => {
  const { search, limit = 10 } = request.query;
  return { search, limit };
});

TypeScript Types

import { FastifyRequest, FastifyReply } from 'fastify';

interface CreateUserBody {
  name: string;
  email: string;
}

interface UserParams {
  id: string;
}

server.post<{
  Body: CreateUserBody;
}>('/users', async (request, reply) => {
  const { name, email } = request.body; // Fully typed
  return { id: '1', name, email };
});

server.get<{
  Params: UserParams;
}>('/users/:id', async (request, reply) => {
  const { id } = request.params;
  return { id };
});

Validation

JSON Schema Validation

const createUserSchema = {
  body: {
    type: 'object',
    required: ['name', 'email'],
    properties: {
      name: { type: 'string', minLength: 2 },
      email: { type: 'string', format: 'email' },
      age: { type: 'number', minimum: 18 },
    },
  },
  response: {
    201: {
      type: 'object',
      properties: {
        id: { type: 'string' },
        name: { type: 'string' },
        email: { type: 'string' },
      },
    },
  },
};

server.post('/users', {
  schema: createUserSchema,
}, async (request, reply) => {
  const { name, email, age } = request.body;
  reply.status(201);
  return { id: '1', name, email };
});

Plugins

Register Plugins

import cors from '@fastify/cors';
import helmet from '@fastify/helmet';
import rateLimit from '@fastify/rate-limit';

// CORS
await server.register(cors, {
  origin: true, // Reflect origin
  credentials: true,
});

// Security headers
await server.register(helmet);

// Rate limiting
await server.register(rateLimit, {
  max: 100, // 100 requests
  timeWindow: '1 minute',
});

Custom Plugin

import fp from 'fastify-plugin';

const myPlugin = fp(async (fastify, options) => {
  // Add decorator
  fastify.decorate('myUtility', () => {
    return 'Hello from plugin!';
  });

  // Add hook
  fastify.addHook('onRequest', async (request, reply) => {
    // Do something on every request
  });
}, {
  name: 'my-plugin',
  fastify: '4.x',
});

await server.register(myPlugin);

// Use decorator
server.get('/test', async (request, reply) => {
  return { message: server.myUtility() };
});

Hooks

// Application hooks
server.addHook('onRequest', async (request, reply) => {
  // Called before route handler
  request.log.info('Incoming request');
});

server.addHook('preHandler', async (request, reply) => {
  // Called after validation, before handler
  if (!request.headers.authorization) {
    reply.code(401).send({ error: 'Unauthorized' });
  }
});

server.addHook('onSend', async (request, reply, payload) => {
  // Called before sending response
  return payload;
});

server.addHook('onResponse', async (request, reply) => {
  // Called after response sent
  request.log.info({ responseTime: reply.getResponseTime() });
});

server.addHook('onError', async (request, reply, error) => {
  // Called on error
  request.log.error(error);
});

Error Handling

// Custom error handler
server.setErrorHandler((error, request, reply) => {
  request.log.error(error);

  if (error.validation) {
    reply.status(400).send({
      error: 'Validation Error',
      message: error.message,
      details: error.validation,
    });
    return;
  }

  reply.status(error.statusCode || 500).send({
    error: error.name,
    message: error.message,
  });
});

// Throw errors in routes
server.get('/error', async (request, reply) => {
  throw new Error('Something went wrong!');
});

// Send error responses
server.get('/not-found', async (request, reply) => {
  reply.code(404).send({ error: 'Not found' });
});

tRPC Integration

import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import { appRouter } from './trpc/router';
import { createContext } from './trpc/context';

// Register tRPC
await server.register(fastifyTRPCPlugin, {
  prefix: '/trpc',
  trpcOptions: {
    router: appRouter,
    createContext,
  },
});

WebSocket Support

import websocket from '@fastify/websocket';

await server.register(websocket);

server.get('/ws', { websocket: true }, (connection, request) => {
  connection.socket.on('message', (message) => {
    connection.socket.send('Hello from server!');
  });
});

Testing

import { test } from 'node:test';
import Fastify from 'fastify';

test('GET /ping returns pong', async (t) => {
  const server = Fastify();

  server.get('/ping', async () => {
    return { pong: 'it worked!' };
  });

  const response = await server.inject({
    method: 'GET',
    url: '/ping',
  });

  t.assert.strictEqual(response.statusCode, 200);
  t.assert.deepStrictEqual(response.json(), { pong: 'it worked!' });
});

Best Practices

  1. Use Plugins: Encapsulate functionality in plugins
  2. Schema Validation: Always validate input with JSON Schema
  3. Error Handling: Set up global error handler
  4. Logging: Use built-in Pino logger
  5. TypeScript: Leverage type safety
  6. Hooks: Use hooks for cross-cutting concerns
  7. Async/Await: Use async handlers
  8. Testing: Use fastify.inject() for testing
  9. Performance: Enable HTTP/2 for better performance
  10. Security: Use @fastify/helmet for security headers

Resources

GitHub リポジトリ

oriolrius/pki-manager-web
パス: .claude/skills/fastify
certificate-authoritycertificate-managementcosmianfastifykmspki

関連スキル

content-collections

メタ

This skill provides a production-tested setup for Content Collections, a TypeScript-first tool that transforms Markdown/MDX files into type-safe data collections with Zod validation. Use it when building blogs, documentation sites, or content-heavy Vite + React applications to ensure type safety and automatic content validation. It covers everything from Vite plugin configuration and MDX compilation to deployment optimization and schema validation.

スキルを見る

creating-opencode-plugins

メタ

This skill provides the structure and API specifications for creating OpenCode plugins that hook into 25+ event types like commands, files, and LSP operations. It offers implementation patterns for JavaScript/TypeScript modules that intercept and extend the AI assistant's lifecycle. Use it when you need to build event-driven plugins for monitoring, custom handling, or extending OpenCode's capabilities.

スキルを見る

evaluating-llms-harness

テスト

This 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.

スキルを見る

polymarket

メタ

This skill enables developers to build applications with the Polymarket prediction markets platform, including API integration for trading and market data. It also provides real-time data streaming via WebSocket to monitor live trades and market activity. Use it for implementing trading strategies or creating tools that process live market updates.

スキルを見る