Building with Purpose 1: Setting up the backend part


All right, here we go, the backend journey starts!
Setting up the project
First and foremost, we create the folder, access it, and run pnpm init
(unlike npm
, this command doesn't require the -y
flag and isn't interactive).
Now we are going to use git init
to use version control for this project and create a public repo so everyone can see it. To do this, we run git init
. This initializes a repository that we’ll push to GitHub. Now we need to create the repo on GitHub. I assume you all know how to create a repo, commit changes, etc. (I’ll skip that part).
Now that our repo is initialized, we can start with the setup for Fastify. If we look at the official documentation, the first thing to do is pnpm add fastify
(note that we’ll be using pnpm, so all npm commands will be pnpm).
First dependencies
We are using TS, so we’ll need a few more things to set up the project.
These things are:
typescript
and@types/node
: For TypeScript support.nodemon
: For automatic reloading during development.ts-node
: To execute.ts
files directly without pre-compiling.@fastify/autoload
: For autoloading plugins and routes.fastify-plugin
: A utility to write plugins.dotenv
: We’ll need it to load the environment variables.
pnpm add fastify-plugin @fastify/autoload
pnpm add typescript @types/node nodemon ts-node dotenv -D
Creating the tsconfig.json
Now we have to initialize and modify a TS config file with npx tsc --init
.
Modifications to make in the tsconfig.json
file:
Set the
"target"
to"ES2017"
(or higher) to avoid Fastify deprecation warnings. In my case, I’m going to useESNext
.Set the
"rootDir"
to"./src"
to specify the root folder for your source files.Set the
"outDir"
to"./build"
to specify an output folder for all emitted files.Enable the
"declaration"
option in the"compilerOptions"
object.Consider setting
"moduleResolution"
to"node"
.
Once done, the src
folder has to be created, and the index.ts
will go inside it.
Creating the index.ts and first run
Following the Fastify guide, we’ll add the bare minimum to test our server:
import type { AddressInfo } from "node:net";
import Fastify from "fastify";
const fastify = Fastify({
logger: true,
});
server.get("/", (req, reply) => {
reply.send({ hello: "wasup!" });
});
const start = async () => {
try {
await server.listen({
port: 3000,
});
console.log(
`Server is now listening on port ${(server.server.address() as AddressInfo).port}`,
);
} catch (err) {
console.error(err);
process.exit(1);
}
};
start();
To configure Nodemon to execute .ts
files using ts-node
, we will create a nodemon.json
in the root directory and paste this:
{
"execMap": {
"ts": "ts-node"
}
}
Once this file is created, we need to add these scripts:
{
"scripts": {
"dev": "nodemon --watch src --exec \"node --loader ts-node/esm\" src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node build/index.js"
}
}
Now we can run pnpm dev
in the terminal to start our server..
Troubleshooting
Warning for “type“: “module“
If encounter (node:94500) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension go to your package.json and add “type“: “module“
.
Warning for TypeError: Unknown file extension ".ts"
for the index.ts file
Looking this up, I found out that the dev script was not configured correctly. We have to configure it to ensure it uses the proper loader. Here’s the modified script::
"dev": "nodemon --watch src --exec \"node --loader ts-node/esm\" src/index.ts"
We also have to modify the tsconfig.json
and change the moduleResolution
to NodeNext
to ensure it’s properly configured for ESM.
If we now run pnpm dev
, we'll see that the address is not logged properly and we get [object Object]
.
To fix this and get the port, we'll need to import the AddressInfo type and add a type assertion to the object to tell TS that it will be that way.
import type { AddressInfo } from "node:net";
...
console.log(`Server is now listening on port ${(server.server.address() as AddressInfo).port}`,);
Now, after running pnpm dev
we should get our message correctly:
(Want prettier logs and environment variables? Check out this article where we configure pino-pretty
to make logs look a bit better.)
It’s time to test the route
We’re running! Yay 👏
Not explained here
All the steps to creating the repository, committing, pushing…
Creating the
README.md
,.gitignore
,.env
and.env.example
files.
That's it for this part.
Salut, Jordi.
Check the repository HERE.
Subscribe to my newsletter
Read articles from Jordi Ollé Ballesté directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jordi Ollé Ballesté
Jordi Ollé Ballesté
Always evolving Full-Stack Developer 👨🏼💻 Mountain addict 🗻