Backend with Fastify - Part 1(Project setup with Typescript, Eslint, Husky, Prettier)

Fastify is a relatively new framework. I have been working with it for a few weeks, and the development experience (DX) with it has been very pleasant.

We will be building an application that allows users to save their favorite movies. This simple application will allow us to focus on understanding the concepts of Fastify, its tools, libraries, testing, authentication etc.

This is part 1 of a series where we start setting up the project.

You can reference the part-1 branch of this repository if you encounter any issues while following along.

We will be using Node.js version 18.

To start setting up the project:

Step 1. Creating Project Directory

Create a new folder and name it "fav-mov" (or whatever you prefer).

mkdir fav-mov

Step 2. Initialize node

Start a new Node.js project.

npm init -y

Step 3. Install Dependencies

Let's install the project dependencies that will be used in the core application.

npm i @fastify/autoload @fastify/cors @fastify/env @fastify/jwt @fastify/sensible @fastify/swagger @fastify/type-provider-typebox fastify fastify-cli fastify-plugin

Now, let's install some helpful dependencies for tooling, linting, and compiling. These tools will make our life as developers easier (until they decide to break on us).

npm i -D @types/node eslint-config-standard-with-typescript fastify-tsconfig rimraf tap tsx typescript ts-node prettier eslint-config-prettier nodemon

💦 That seems like a lot, but don't worry; we'll explore each of them slowly as we build the application.

Step 4. Set up Typescript

Create a tsconfig.json file.

touch tsconfig.json

Add the following content to tsconfig.json:

{
  "extends": "fastify-tsconfig",
  "compilerOptions": {
    "outDir": "dist",
    "declaration": false,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": [".eslintrc.js"]
}

We are using settings from fastify-tsconfig, which is a shared typescript configuration for fastify projects.

Step 5. Set up EsLint and Prettier

Create a .eslintrc.js file.

touch .eslintrc.js

Add the following content to .eslintrc.js:

module.exports = {
  extends: ['standard-with-typescript','prettier'],
  parserOptions: {
    project: "./tsconfig.json",
  },
  rules: {
    '@typescript-eslint/consistent-type-assertions': 'off',
    '@typescript-eslint/no-floating-promises': 'off',
    '@typescript-eslint/strict-boolean-expressions': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/naming-convention': 'off',
    },
};

This is a basic .eslintrc.js file; you can modify the rules or add additional plugins as you prefer.

Now, let's create a .prettierrc file.

touch .prettierrc

Add the following content to .prettierrc, adjusting it to your preferences:

{
    "semi": false,
    "singleQuote": true,
    "arrowParens": "avoid"
}

Now, let's create an index.ts file inside an src folder, which will be the entry point for our application.

mkdir src
touch src/index.ts

For now, let's just add a simple console log statement to index.ts:

console.log('Hello!!')

Next, let's modify the package.json file's scripts to allow us to both start the application in development mode and build it:

{
    scripts: {
        "build": "rimraf dist && tsc",
        "dev": "nodemon src/index.ts",
        "start": "node dist/index.js"
    }

}

Now:

  • npm run dev will run the application in development mode and watch for any changes.

  • npm run build will compile the TypeScript and create a production build.

  • npm run start will start the production build.

Step 6. Setting up Husky

We're almost done setting up the project, but there's one last thing: setting up this project as a Git repository and adding Husky.

Husky is a git hook we can use to make our developer life easier. We can use it to automate linting and applying code formatting.

Initialize a Git repository:

git init --initial-branch=main

Install Husky as a dev dependency:

npm i -D husky

Run the following command to add a script in your package.json file:

npm pkg set scripts.prepare="husky install"

Now run this script

npm run prepare

This will create a .husky folder in your root directory, which you can see with the ls -la command.

Create a pre-commit hook for Husky with the following command:

npx husky add .husky/pre-commit

This will create a pre-commit file inside the .husky folder. Modify it to match the following:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged

Finally, modify your package.json file and add lint-staged:

scripts:{
 // has the scripts such as dev, start
},
"dependencies":{
 // dependencies list
},
"devDependencies":{
 // dev dependencies list
},
"lint-staged": {
    "*.ts": [
      "prettier --config .prettierrc 'src/**/*.ts' --write",
      "eslint . --ext .ts --fix"
    ]
}

Now, whenever you make a Git commit, the Git hook will run to first lint and format the code based on the Prettier config.

Congratulations! We've completed the tedious setup part. In the next part, we will finally move on to using Fastify to create our first route.