| name | fastify-plugin |
| description | Guide for creating Fastify plugins with TypeScript, ESM, and fastify-plugin wrapper. Use when adding new plugins to app/src/plugins/. |
Fastify Plugin Development
This skill provides patterns and conventions for creating Fastify plugins in this repository.
Directory Structure
Plugins are located in app/src/plugins/. Each plugin is a single TypeScript file that exports a default async function wrapped with fastify-plugin.
Plugin Template
import type { FastifyInstance } from "fastify";
import fp from "fastify-plugin";
async function pluginName(fastify: FastifyInstance): Promise<void> {
// Plugin implementation
}
export default fp(pluginName, {
name: "plugin-name",
dependencies: [], // List plugin dependencies if any
});
Best Practices
- Always use fastify-plugin wrapper: Wrap plugins with
fp()to expose decorators to parent scope - Declare dependencies: List other plugins this plugin depends on in the options
- Type augmentation: Extend Fastify types when adding decorators:
declare module "fastify" {
interface FastifyInstance {
myDecorator: string;
}
interface FastifyRequest {
customProperty: CustomType;
}
}
- ESM imports: Use
.jsextensions for relative imports (TypeScript compiles to ESM) - Node.js builtins: Use
node:protocol prefix (e.g.,import * as path from "node:path") - Type imports: Use
import type { ... } from "pkg"for type-only imports
Existing Plugins Reference (16 plugins)
accepts-serializer.ts- CBOR response serialization with @fastify/accepts-serializerauth.ts- Firebase authentication with request.user decoratorcbor-parser.ts- CBOR request body parsingcors.ts- CORS configuration with @fastify/corserror-handler.ts- Global error handling with RFC 9457 Problem Details responsesfirebase.ts- Firebase Admin SDK initializationhelmet.ts- Security headers with @fastify/helmetlifecycle.ts- Server lifecycle hooks and graceful shutdownlogging.ts- Request/response logging with timingrequestid.ts- Request ID generation and header propagationschema-discovery.ts- Schema link header injection for responsesschema-registry.ts- Shared TypeBox schema registrationsensible.ts- HTTP error utilities with @fastify/sensibleswagger.ts- OpenAPI documentation with @fastify/swaggerunder-pressure.ts- Health checks and system pressure monitoringvary-header.ts- Vary: Accept header for proper caching
Testing Requirements
Each plugin must have a corresponding test file in app/tests/unit/plugins/. See the vitest-testing skill for testing patterns.
Commands
cd app
npm run build # Build and verify TypeScript compilation
npm run check # Run Biome linter and formatter
npm run check:fix # Auto-fix linting issues
npm run test # Run all tests including plugin tests
Boundaries
- Do not modify
app/src/app.tsunless adding new plugin registration - Do not add plugins that duplicate existing functionality
- Always add corresponding unit tests for new plugins