Guide for setting up new Node.js projects
No TypeScript. Use JavaScript ES6+ syntax (
let,const,async/await, etc.).
- Use Node.js v20 or alternative LTS (long-term support) versions
- Install
nvmto manage node.js version - Run
nvm use 20to switch to node.js version 20 - Add
.nvmrcfile to every project and include20to set node.js version - Run
nvm useto read version from.nvmrcfile and switch to respective version
- Install
prettierglobally for automatic code formatting on file save - Turn on "Prettier: Single Quote" and "Prettier: Trailing Comma" in VS Code settings. Open the Command Palette (Command + Shift + P) and type "Preferences: Open Settings (JSON)". Select it. Add the following lines:
{
"prettier.singleQuote": true,
"prettier.trailingComma": "es5"
}Alternative to settings.json - visual settings:

- Create new folder for new project
- Copy
modules/setup-new-project.jsfile to new project folder - Run
node setup-new-project.jsto setup all files and project structure
- Create new folder for new project
- Create a new git repo on GitHub. Run
git initto initialize repo locally.git remote add origin <repo-url>to add remote repo.- Use Source Control tab in VS Code to add, commit and push files to GitHub repo.
- Init node.js project by
npm init -yto createpackage.jsonfile - Install
npm i dotenvlocally to read variables from.envfile
Create:
README.mdmodulesfolder that includes all files for projectoutputfolder for saving any type of logging files during development, e.g. caching OpenAI responses, writing log files, etc.modules/helpers.jsfile that includes any type of generic helper functions, such as writing stuff to files (toFile(...)), de/compression, command-line confirm, etcconfig/index.jsfile that includes all the configuration variables for the project, such as API keys, URLs, etc..envfile to store all the environment variables, such as API keys, URLs, etc..gitignorefile to ignorenode_modules,.env,outputand other files/folders that should not be pushed to GitHub.nvmrcfile to specify the node.js version for the project
File naming convention:
my-module.js: use Kebab-case for file names, e.g.my-module.js,my-module-name.js, etc.const myFunction = () => { ... }: use camelCase for function names, e.g.myFunction,myFunctionName, etc.
Structure:
project-name
├── .gitignore
├── .nvmrc
├── .env // add all sensitive environment variables here
├── README.md
├── config
│ └── index.js // load .env variables and others to export them
├── modules // includes app logic
│ ├── helpers.js
│ ├── module-name1.js
│ └── module-name2.js
├── output
│ ├── log.txt
│ └── cache.json
├── package.json // auto-generated after `npm init -y`
├── package-lock.json // auto-generated after `npm install <package-name>`
├── node_modules // auto-generated after `npm install <package-name>`
File Structure:
Start each file by importing required modules. Import modules in the following order:
../configorrequire('dotenv').config()- Native modules, eg
fs,path, etc. - Third-party modules, eg
axios,express, etc. - Local modules, eg
./helpers,./module-name1, etc.
const config = require('../config'); // config variables
const fs = require('fs'); // native module
const lodash = require('lodash'); // installed via `npm i axios`
const helpers = require('./helpers'); // local module- lodash
- axios
- dotenv
- pm2
- When deciding what npm package to install, select the packages with higher download counts to ensure a larger community support
- Use UUIDs to create unique IDs
- Use Docker for databases and other services (eg PostgreSQL, ElasticSearch, Redis, etc.)
- Create
PROTOCOL.mdoutlining steps on how to perform a repeatable process and clean up once done - Use
.jsonlfiles for large JSON files - Sort JSON(L) files by
filedAtor similar timestamp fields to make it easier to read - Use
JSON.stringify(obj, null, 2)to format JSON objects - Use
pm2to run scripts in the background.- Use
ecosystem.config.jsto configurepm2to define and run scripts. pm2 start ecosystem.config.jsto start the scriptspm2 logsto view logs,pm2 stop <id>to stop the scrip,pm2 restart <id>to restart the script.
- Use
Setup VSCode to run files in terminal on shift + enter:
- Open the Command Palette (Command + Shift + P) and type "Preferences: Open Keyboard Shortcuts (JSON)". Select it.
- Add:
{
"key": "shift+enter",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "node ${file}\u000D"
},
"when": "resourceExtname == .js || resourceExtname == .mjs"
}Format file on save:
- Open the Command Palette (Command + Shift + P) and type "Preferences: Open Settings (JSON)". Select it.
- Add:
{
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.tabSize": 2 // Set the indent size to 2 spaces for JavaScript
},
"prettier.singleQuote": true,
"prettier.trailingComma": "es5"
}Turn Copilot on/off via cmd + shift + t:
- Install extension "Settings Cycler" (extension ID: hoovercj.vscode-settings-cycler)
- Open
keybindings.jsonand add:
{
"key": "cmd+shift+t",
"command": "settings.cycle.copilot",
"when": "editorFocus"
}- Open
settings.jsonand add:
"settings.cycle": [
{
"id": "copilot",
"overrideWorkspaceSettings": true,
"values": [
{
"github.copilot.enable": {
"*": false,
"markdown": false
},
"github.copilot.inlineSuggest.enable": false,
"github.copilot.editor.enableAutoCompletions": false
},
{
"github.copilot.enable": {
"*": true,
"markdown": true
},
"github.copilot.inlineSuggest.enable": true,
"github.copilot.editor.enableAutoCompletions": true
}
]
}
],const run = async () => {...}
if (require.main === module) {
run();
}Switch Node.js version automatically when opening a project and .nvmrc is present in project dir.
- If
echo $SHELL==zsh, edit file~/.zshrc. - If
echo $SHELL==bash, edit file~/.bashrc.
nano ~/.bashrc # or ~/.zshrc
# add line
[ -f .nvmrc ] && nvm use > /dev/nullEnsure shell shows project dir folder-name $:
nano ~/.bashrc # or ~/.zshrc
# add line
# for zsh shell
PS1='%B%F{blue}%1d%f%b $ '
# for bash shell
PS1='\[\033[01;34m\]\W\[\033[00m\] $ '