Home › Node.js / TypeScript › Fastify 5 API rules
Fastify 5 API rules
Cursor rules for Fastify 5 APIs in TypeScript: plugins and encapsulation, JSON schema validation, hooks, and inject tests.
CursorNode.js / TypeScript
How to use
Save this as .cursor/rules/fastify.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
Note: Review and test before use. Provided as is, without warranty. See Terms.
.cursor/rules/fastify.mdcDownload ---
description: Fastify 5 API conventions
globs: ["src/**/*.ts"]
alwaysApply: false
---
# Fastify 5
- Build the app in `src/app.ts` as `export async function buildApp(opts)` returning a Fastify instance; `src/server.ts` calls `listen`. Tests use `app.inject()`, not a running server.
- Organize features as plugins (`src/routes/orders/index.ts` exporting an async plugin). Use `fastify-plugin` only for plugins that must share decorators with the parent (DB client, auth); otherwise keep encapsulation.
- Every route declares a `schema` (body, querystring, params, response) with TypeBox (`@sinclair/typebox` + `TypeBoxTypeProvider`) or zod via `fastify-type-provider-zod`. Response schemas both document and strip extra fields.
- Decorate shared services (`app.decorate('db', db)`) with TypeScript declaration merging for types.
- Auth in an `onRequest`/`preHandler` hook or `@fastify/jwt`; don't repeat checks in handlers.
- Errors: throw `httpErrors` from `@fastify/sensible` or set `reply.code()`; one `setErrorHandler` for formatting. Don't leak stack traces.
- Use the built-in pino logger (`request.log.info({ orderId }, 'created')`); no `console.log`.
- Register `@fastify/helmet`, `@fastify/cors` (explicit origins), and `@fastify/rate-limit` where relevant.
- Async handlers return the payload; don't mix `return` with `reply.send()`.
- Close resources in an `onClose` hook.
## Done when
`tsc --noEmit`, lint, and `app.inject()` tests for each new route (success and validation failure) pass.