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 iA 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 Initnpm init -y
npm pkg set type=module
npm pkg set name=my-package
npm pkg set author=my-name
npm iAdd .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/dotenvxMain .env file remains tracked, replace .env* entries in .gitignore with:
.env.keys
.env.local
.env.*.local
npm i -D typescript @types/nodeInitialize 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 pkgroll@2.4.0
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-prettierInitialize flat config:
npx @eslint/create-config@1.1.0
√ 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? · NoUpdate 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.