Fastify Project Architecture Design
Project Initialization
Create and initialize a new Fastify project:
mkdir my-fastify-app
cd my-fastify-app
npm init -y
npm install fastifyDirectory Structure
A typical Fastify project directory structure:
my-fastify-app/
├── src/
│ ├── routes/
│ │ └── index.js
│ ├── controllers/
│ │ └── index.js
│ ├── services/
│ │ └── userService.js
│ ├── middlewares/
│ │ └── auth.js
│ ├── plugins/
│ │ └── logger.js
│ ├── models/
│ │ └── user.js
│ └── index.js
├── tests/
│ └── index.test.js
├── .env
└── package.jsonsrc/routes/: Route definitions.src/controllers/: Business logic controllers.src/services/: Service layer for business logic.src/middlewares/: Middleware functions.src/plugins/: Fastify plugins.src/models/: Data models.tests/: Test files..env: Environment variable configuration.package.json: Project dependencies.
Main Application Entry (src/index.js)
const fastify = require('fastify')({ logger: true });
// Load plugins
fastify.register(require('./plugins/logger'));
// Register routes
fastify.register(require('./routes/index'));
// Register middleware
fastify.register(require('./middlewares/auth'));
// Start server
const start = async () => {
try {
await fastify.listen({ port: process.env.PORT || 3000 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();Routes (src/routes/index.js)
module.exports = async function (fastify, opts) {
// Import controller
const controller = require('../controllers/index');
// Define routes
fastify.get('/', controller.home);
fastify.post('/users', controller.createUser);
};Controller (src/controllers/index.js)
const userService = require('../services/userService');
// Controller methods
exports.home = async (request, reply) => {
return { hello: 'world' };
};
exports.createUser = async (request, reply) => {
const user = await userService.createUser(request.body);
return user;
};Service Layer (src/services/userService.js)
const userModel = require('../models/user');
// Service layer methods
exports.createUser = async (userData) => {
const user = new userModel(userData);
return await user.save();
};Data Model (src/models/user.js)
Assuming MongoDB:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: String,
email: String,
password: String
});
module.exports = mongoose.model('User', userSchema);Middleware (src/middlewares/auth.js)
module.exports = async function (fastify, opts) {
fastify.addHook('onRequest', async (request, reply) => {
// Middleware logic
// ...
});
};Plugin (src/plugins/logger.js)
module.exports = async function (fastify, opts) {
fastify.addHook('onRequest', async (request, reply) => {
fastify.log.info(`Request received: ${request.url}`);
});
};Environment Variables (.env)
PORT=3000
MONGO_URI=mongodb://localhost:27017/mydbTests (tests/index.test.js)
Using Mocha and Chai:
const chai = require('chai');
const chaiHttp = require('chai-http');
const fastify = require('../src/index');
const should = chai.should();
chai.use(chaiHttp);
describe('Users', () => {
it('should POST a user', async () => {
const user = {
name: 'John Doe',
email: 'john.doe@example.com',
password: 'password123'
};
const res = await chai.request(fastify.server)
.post('/users')
.send(user);
res.should.have.status(200);
res.body.should.be.an('object');
res.body.should.have.property('name').eql(user.name);
});
});



