A practical project template and recipe for a modern Node.js backend application project.
Requires Node.js 18+.
- TypeScript: run via
tsx
, build viapkgroll
- Native ESM
- Dotenv: multi env and encryption
- ESLint + Prettier
- Jest
git clone https://github.com/bisubus/node-app-template
cd node-app-template
npm run init -- --author=my-name --package=my-package
git add -u
git commit -m "Init template"
npm i
A step-by-step recipe for customization.
Source files are located in src/
, test files in src/__test__
.
Empty initial commit makes a rebase easier.
git init
git commit --allow-empty -m Init
npm init -y
npm pkg set type=module
npm pkg set name=my-package
npm pkg set author=my-name
npm i
Add .gitignore.
Add LICENSE and update info.
Add env.ts to autoload .env.*
files similarly to dotenv-flow
.
npm i -D cross-env
npm i @dotenvx/dotenvx
Main .env
file remains tracked, replace .env*
entries in .gitignore
with:
.env.keys
.env.local
.env.*.local
npm i -D typescript @types/node
Initialize TS config:
npx tsc --init
Update tsconfig.json
:
"compilerOptions": {
...
"target": "es2023",
"lib": ["es2023"],
"module": "nodenext",
"moduleResolution": "nodenext",
"paths": { "@/*": ["./src/*"] },
"typeRoots": ["./src/types", "./node_modules/@types"]
"outDir": "./dist",
"declarationDir": "./types",
...
},
"include": ["src", "env.ts"],
"exclude": ["node_modules"],
The scripts to run the app by compiling TS on the fly:
npm i -D tsx
npm pkg set scripts.start="cross-env NODE_ENV=production node --import=tsx --import=./env.ts src/index.ts"
npm pkg set scripts.dev="node --import=tsx --import=./env.ts src/index.ts"
npm pkg set scripts.dev:debug="node --import=tsx --import=./env.ts --inspect-brk src/index.ts"
npm pkg set scripts.dev:watch="tsx watch --ignore !./src/**/* --clear-screen=false --import=./env.ts src/index.ts"
The script to bundle the app for deployment:
npm i -D [email protected]
npm pkg set scripts.build="pkgroll --sourcemap --tsconfig=tsconfig.build.json"
Add tsconfig.build.json
:
{
"compilerOptions": {
"module": "es2022",
"moduleResolution": "bundler"
},
"extends": "./tsconfig.json"
}
Add entry point to package.json
:
"exports": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
}
ESLint 8 for the compatibility with tools:
npm i -D eslint@8 @types/eslint@8 globals @eslint/js@8 typescript-eslint@7 prettier eslint-config-prettier eslint-plugin-prettier
Initialize flat config:
npx @eslint/[email protected]
√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm
√ Which framework does your project use? · none
√ Does your project use TypeScript? · typescript
√ Where does your code run? · node
× Would you like to install them now? · No
Update eslint.config.js to add Prettier and customize the rules.
The scripts:
npm pkg set scripts.lint="eslint ."
npm pkg set scripts.lint:fix="eslint --fix ."
npm i -D ts-jest @types/jest
npx ts-jest config:init
npm pkg set scripts.test="jest"
Update jest.config.js to configure test file locations.