Skip to content

flaviodelgrosso/fastify-forge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

400 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚑ Fastify Forge

A production-ready Fastify monorepo template β€” scaffold, build, and ship high-performance Node.js APIs in seconds.

npm version License: MIT Node.js pnpm TypeScript Fastify


Why Fastify Forge?

Starting a new Node.js API project means wiring up the same boilerplate every time β€” auth, validation, logging, CORS, rate-limiting, OpenAPI docs, database migrations… Fastify Forge ships all of it, pre-configured and production-grade, in a single npx command.

Built on Fastify 5 β€” one of the fastest HTTP frameworks for Node.js β€” and organised as an Nx monorepo, the template gives you a clean, scalable foundation you can grow into without ever fighting the scaffolding again.


✨ Features

Category What's included
πŸš€ Performance Fastify 5 + Pino structured logging + @fastify/under-pressure overload protection
πŸ” Authentication Better Auth with email/password, admin plugin, session caching & cookie management
πŸ—„οΈ Database Drizzle ORM + PostgreSQL 17 with pre-built users, sessions & accounts schema
βœ… Validation End-to-end type-safe schemas via TypeBox + @fastify/type-provider-typebox
πŸ“– OpenAPI Swagger UI at /api/docs + Better Auth's OpenAPI integration, auto-generated from route schemas
πŸ›‘οΈ Security @fastify/helmet, @fastify/cors, @fastify/rate-limit (with 404-route scan protection)
πŸ“ Auto-loading Plugin & route discovery via @fastify/autoload β€” drop a file, it's registered
πŸͺ Route Hooks Cascading auth.hook.ts pattern keeps authentication logic out of route handlers
βš™οΈ Config Type-safe environment variables via @fastify/env + TypeBox schema
🐳 Docker PostgreSQL 17 via docker-compose.yaml with health checks and persistent volumes
πŸ”„ Graceful shutdown close-with-grace ensures in-flight requests complete before the server exits
πŸ—οΈ Monorepo Nx workspace with affected-only CI, build caching, and Docker targets
🎨 DX Husky, commitlint (Conventional Commits), Prettier, ESLint 9 flat config, Changesets, syncpack
πŸ› οΈ CLI Interactive scaffolder β€” npx fastify-forge to clone, configure, and initialise a new project

πŸ“¦ Tech Stack

Layer Technology
Runtime Node.js β‰₯ 24
Framework Fastify 5
Language TypeScript 5
ORM Drizzle ORM
Database PostgreSQL 17
Auth Better Auth
Logging Pino + pino-pretty
Validation TypeBox
Monorepo Nx
Package manager pnpm 10

πŸš€ Quick Start

Option A β€” CLI scaffolder (recommended)

npx fastify-forge --name my-api

The interactive CLI will:

  1. Clone the template into ./my-api
  2. Strip git history and set up a fresh repo
  3. Copy .env.example β†’ .env
  4. Optionally initialise git and install dependencies

Option B β€” Clone manually

git clone https://github.com/flaviodelgrosso/fastify-forge.git my-api
cd my-api
pnpm install

🏁 Getting Started

1. Configure environment variables

Copy the example file and fill in your values:

cp apps/api/.env.example apps/api/.env
Variable Description Default
HOST Server bind address localhost
PORT Server port 8080
LOG_LEVEL Pino log level (trace | debug | info | warn | error) info
POSTGRES_HOST PostgreSQL host β€”
POSTGRES_PORT PostgreSQL port 5432
POSTGRES_USER PostgreSQL user β€”
POSTGRES_PASSWORD PostgreSQL password β€”
POSTGRES_DB PostgreSQL database name β€”
BETTER_AUTH_SECRET Secret key for Better Auth (min 32 chars) β€”

2. Start the database

docker compose up -d

3. Run database migrations

pnpm --filter @fastify-forge/db db:push

4. Start the development server

pnpm start

The API is now running at http://localhost:8080 πŸŽ‰


πŸ“ Project Structure

fastify-forge/
β”œβ”€β”€ apps/
β”‚   └── api/                    # Main Fastify application
β”‚       └── src/
β”‚           β”œβ”€β”€ main.ts         # Server entry point & graceful shutdown
β”‚           β”œβ”€β”€ app.ts          # Plugin & route registration, error handlers
β”‚           β”œβ”€β”€ auth.ts         # Better Auth configuration
β”‚           β”œβ”€β”€ plugins/
β”‚           β”‚   β”œβ”€β”€ external/   # Third-party Fastify plugins
β”‚           β”‚   β”‚   β”œβ”€β”€ cors.ts
β”‚           β”‚   β”‚   β”œβ”€β”€ env.ts          # Type-safe env schema
β”‚           β”‚   β”‚   β”œβ”€β”€ helmet.ts
β”‚           β”‚   β”‚   β”œβ”€β”€ multipart.ts
β”‚           β”‚   β”‚   β”œβ”€β”€ rate-limit.ts
β”‚           β”‚   β”‚   β”œβ”€β”€ sensible.ts
β”‚           β”‚   β”‚   β”œβ”€β”€ swagger.ts      # OpenAPI + Swagger UI
β”‚           β”‚   β”‚   └── under-pressure.ts
β”‚           β”‚   └── internal/   # App-specific plugins
β”‚           β”‚       β”œβ”€β”€ authentication.ts   # Better Auth plugin
β”‚           β”‚       └── db.ts               # Drizzle connection
β”‚           └── routes/
β”‚               β”œβ”€β”€ health.ts           # GET /health
β”‚               β”œβ”€β”€ root.route.ts       # Root route
β”‚               └── api/
β”‚                   β”œβ”€β”€ auth.hook.ts    # Session guard (cascades to child routes)
β”‚                   └── v1/
β”‚                       └── protected.ts    # Example protected endpoint
β”‚
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ db/                     # @fastify-forge/db β€” Drizzle client & schema
β”‚   β”‚   └── src/
β”‚   β”‚       β”œβ”€β”€ index.ts        # Drizzle client export
β”‚   β”‚       └── schema.ts       # users, sessions, accounts tables
β”‚   └── logger/                 # @fastify-forge/logger β€” Pino logger instance
β”‚       └── src/
β”‚           └── index.ts
β”‚
β”œβ”€β”€ cli/                        # npx fastify-forge scaffolder
β”œβ”€β”€ docker-compose.yaml         # PostgreSQL 17 service
β”œβ”€β”€ nx.json                     # Nx workspace configuration
β”œβ”€β”€ pnpm-workspace.yaml         # pnpm catalogs & workspace config
└── eslint.config.js            # ESLint 9 flat config

πŸ”Œ Plugins at a Glance

Plugins are auto-discovered from the plugins/ directory via @fastify/autoload. Adding a new plugin is as simple as dropping a file:

// apps/api/src/plugins/external/my-plugin.ts
import fp from 'fastify-plugin'
import myPlugin from 'fastify-my-plugin'

export default fp(async (fastify) => {
  await fastify.register(myPlugin, { /* options */ })
})

Route hooks & authentication

The auth.hook.ts file lives next to the api/ route folder and cascades down to every child route automatically. Any route placed inside api/ is protected by session validation β€” no extra wiring needed.

routes/
└── api/
    β”œβ”€β”€ auth.hook.ts   ← runs for all routes below this directory
    └── v1/
        └── protected.ts   ← session already validated βœ“

πŸ—„οΈ Database

The @fastify-forge/db package exports a ready-to-use Drizzle ORM client and a starter schema:

  • users β€” id, email, name, role (admin | user), image, ban management, timestamps
  • sessions β€” token, expiry, user agent, IP address, impersonation support
  • accounts β€” OAuth provider accounts with access/refresh token storage

Useful database commands

# Generate a new migration
pnpm --filter @fastify-forge/db db:generate

# Push schema to database (dev)
pnpm --filter @fastify-forge/db db:push

# Open Drizzle Studio
pnpm --filter @fastify-forge/db db:studio

πŸ” Authentication

Authentication is powered by Better Auth with the following setup out of the box:

  • Email & password sign-up / sign-in
  • Session caching (5-minute cookie cache) to reduce database hits
  • Admin plugin for user management endpoints
  • OpenAPI integration β€” auth routes appear in the Swagger UI at /api/docs
  • 1-week session expiry with daily refresh
// Sign in β€” POST /api/auth/sign-in/email
{
  "email": "user@example.com",
  "password": "supersecret"
}

πŸ“– API Documentation

Swagger UI is served at /api/docs and is automatically populated from TypeBox schemas on your route definitions. Add a schema to any route and it appears instantly:

app.route({
  url: '/users/:id',
  method: 'GET',
  schema: {
    tags: ['Users'],
    params: Type.Object({ id: Type.String({ format: 'uuid' }) }),
    response: { 200: UserSchema },
  },
  handler: async (req) => getUserById(req.params.id),
})

πŸ“œ Available Scripts

Run these from the workspace root:

Command Description
pnpm start Start all apps in parallel
pnpm build Build all packages and apps
pnpm lint Lint all projects
pnpm typecheck Type-check all projects
pnpm test Run all tests
pnpm format Format all files with Prettier
pnpm clean Remove all build artifacts and node_modules

Nx only re-runs tasks for projects affected by your changes, keeping feedback loops fast.


πŸ› οΈ CLI Reference

npx fastify-forge [options]
Flag Description
--name <name> Project name / directory (prompted interactively if omitted)
--no-git Skip git repository initialisation

🀝 Contributing

Contributions are welcome! Please follow Conventional Commits for commit messages β€” the commit-lint hook will remind you.

# Fork & clone your fork
git clone https://github.com/<your-handle>/fastify-forge.git
cd fastify-forge
pnpm install

# Create a feature branch
git checkout -b feat/my-awesome-feature

# Make your changes, then open a PR πŸš€

Releases are managed via Changesets. If your PR includes a user-facing change, add a changeset:

pnpm changeset

πŸ“„ License

MIT Β© Flavio Del Grosso


About

πŸš€ Fastify monorepo template for building scalable, high-performance Node.js web applications with ease

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors