Project structure
So far the whole server fits in one file, but as the API grows it is easier to split it. The usual approach separates building the application (src/app.js) from starting it (src/server.js): this way tests can create the application without taking a port.
Project folders
blog-api/
package.json
src/
app.js builds the application
server.js starts it: listen
routes/
posts.js post routes
comments.js comment routes
plugins/
db.js shared parts: the database and so on
test/
posts.test.js testsYou create the routes and plugins folders yourself — Fastify does not require a fixed structure, this is a common convention.
A routes file
Create src/routes/posts.js. In Fastify routes are written as a function that receives the application instance:
// src/routes/posts.js
export default async function postRoutes(app) {
app.get('/posts', async () => {
return [{ id: 1, title: 'First post' }];
});
}Such a function is called a plugin. Plugins get a whole chapter later; for now it is enough to know that they are connected with register.
Building the application
Create src/app.js. It creates the instance, registers the routes and returns it without starting:
// src/app.js
import Fastify from 'fastify';
import postRoutes from './routes/posts.js';
export function buildApp(options = {}) {
const app = Fastify(options);
app.register(postRoutes);
return app;
}The function takes options, so the server can turn the logger on while a test leaves it off.
Starting
Replace the contents of src/server.js:
// src/server.js
import { buildApp } from './app.js';
const app = buildApp({ logger: true });
try {
await app.listen({ port: 3000 });
} catch (error) {
app.log.error(error);
process.exit(1);
}Run npm run dev and open http://localhost:3000/posts — you see an array with one post.
What goes where
| File | Responsible for |
|---|---|
src/app.js | Which plugins and routes the application has |
src/server.js | Port, host, starting and stopping the process |
src/routes/*.js | API addresses and their handlers |
src/plugins/*.js | Shared resources: database, auth, settings |
Common mistake
In ES modules the path to your own file includes the extension: import postRoutes from './routes/posts.js'. Without .js Node.js fails with ERR_MODULE_NOT_FOUND.