Fastify
About
This Claude Skill provides expert guidance for building high-performance Node.js web servers and REST APIs using the Fastify framework. It covers server setup, routing, plugins, hooks, validation, error handling, and TypeScript integration. Use this skill when you need assistance with Fastify's schema-based validation, plugin architecture, or performance optimization.
Documentation
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
- Use Plugins: Encapsulate functionality in plugins
- Schema Validation: Always validate input with JSON Schema
- Error Handling: Set up global error handler
- Logging: Use built-in Pino logger
- TypeScript: Leverage type safety
- Hooks: Use hooks for cross-cutting concerns
- Async/Await: Use async handlers
- Testing: Use fastify.inject() for testing
- Performance: Enable HTTP/2 for better performance
- Security: Use @fastify/helmet for security headers
Resources
- Documentation: https://www.fastify.io/docs/latest/
- GitHub: https://github.com/fastify/fastify
- Plugins: https://www.fastify.io/ecosystem/
Quick Install
/plugin add https://github.com/oriolrius/pki-manager-web/tree/main/fastifyCopy 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.
webapp-testing
TestingThis Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.
business-rule-documentation
MetaThis skill provides standardized templates for systematically documenting business logic and domain knowledge following Domain-Driven Design principles. It helps developers capture business rules, process flows, decision trees, and terminology glossaries to maintain consistency between requirements and implementation. Use it when documenting domain models, creating business rule repositories, or bridging communication between business and technical teams.
