Backend Boilerplate for NodeJs-ExpressJs-MongoDB
Tags: node, javascript, webdev, mongodb
Published: 2022-10-09 21:29:42

When i was learning backend web developement. I had not found any proper resource for Backend Web Development. But, i have tried my best to learn. Started googling, learnt using youtube and documentation websites. <br>
Then after, i used to work in same file  app.js or index.js 
Later on, It was very hard for me to work on Big Projects.<br><br>
**Before Start why file structure is important?**
1) Helps you to find your files quickly in future.
2) Other developers can understand your files and don't face much difficulty
3) Easy for debugging
4) More importantly clean code, because **it allows you to clearly communicate with the next person who works with what you've written.** <br><br>

## File Structure

![file_structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6g0drf5ricl3cu9009dj.png)
### configuration
→ In this directory, we usually connect our database i.e. MongoDB using mongoose.<br>
→ And also to manage passport, it is Express-compatible authentication middleware for Node.js . Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as strategies and this directory is mainly used to take care of configuration part.<br>

#### → Structure for **db.js**
```javascript
import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();
const MONGO_URL = process.env.MONGO_URL || "mongodb://localhost:27017/test"

// console.log(MONGO_URL)

// Connect Database
export const connectDB = mongoose.connect(MONGO_URL,{
useNewUrlParser:true,
useUnifiedTopology:true
})
.then(console.log("DB Connected Succesfully...."))
.catch((err)=>{
console.log("DB Connection Failed!")
console.log(err)
process.exit(1)
});

export default connectDB;
```
<br><br>

### models
Here we implement our schemas in order to create collections in each document.

#### → Structure of **user.js**

```javascript
// Import Dependencies
import mongoose  from "mongoose";
import validator from "validator";
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";

const userSchema=new mongoose.Schema({

username:{type:String,required:true,maxlength:[40,'Name should be under 40 characters.']},

email:{type:String,required:[true,'Please provide an email'],validate:[validator.isEmail,'Please enter email in correct format'],unique:true},

password:{type:String,required:true,minlength:[6,"Password should be of atleast 6 characters."],
},

role:{type: [{type: String,enum: ['admin', 'user']}],default:['user']},
forgotPasswordToken:String,
forgotPasswordExpiry:Date
},
{timestamps:true})

const User = mongoose.model("User",userSchema);
export default User;
```<br>
<br>
### controllers
Controller functions to get the requested data from the models, create an HTML page displaying the data, and return it to the user to view in the browser.<br>
#### → Structure of **userController.js**

```javascript
// Import Model
import User from "../models/User.js"

// Making Promise
import bigPromise from "../middlewares/bigPromise.js"

export const createUser = bigPromise(async(req,res,next)=>{
const {username,email,password}=req.body;

if((!username) || (!email) || (!password)){
return res.status(400).json({
success:false,
message:"All fields are required!"
})}

const existingUser = await User.findOne({email:email})

if(existingUser){
return res.status(501).json({
success:true,
message:"User Already Exists !",
})}

else{
const user=await User.create({
username,
email,
password
})

return res.status(201).json({
success:true,
message:"User Created Successfully !",
data:user
})
}
})
```
<br>
<br>
### middlewares
The main purpose of the middleware is **to modify the req and res objects, and then compile and execute any code that is required**. It also helps to terminate the request-response session and call for the next middleware in the stack.

```javascript
myCustomMiddleware (req,res,next)
{
// My Customized Middleware is here.
}
```<br>
### routes
"Routes" to forward the supported requests (and any information encoded in request URLs) to the appropriate controller functions.
#### → Structure of **userRoutes.js**

```javascript
import express from "express"
const router = express.Router()

// import controllers
import {createUser} from "../controllers/userController.js"

router.route("/createUser").post(createUser)
export default router;
```
<br><br>
## utils
In "Utils" we put functions to handle error based on api and etc. Also "utils" module provides some functions to print formatted strings as well as some 'utility' functions that are helpful for debugging purposes. Use require('utils') to access these functions.<br>
## .env
The .env file contains the individual user environment variables that override the variables set in the /etc/environment file. You can customize your environment variables as desired by modifying your . env file.<br>
#### Example :

```
#JWT
APP_PORT=9000

#PREFIX app path
APP_PRIFIX_PATH=/APP_PRIFIX_PATH

#JWT
JWT_SECRET=APLHABETAGAMA
JWT_EXPIRE=1y

# Database config

# If you want to use database URI with DB_URI
DB_URI=
DB_USERNAME=admin
DB_PASSWORD=admin
```<br>
#### → Structure of **app.js**
Here, we import main dependencies like regular middlewares, cookie-parser, routes management and router middleware.

```javascript
import express  from "express"
import  dotenv  from "dotenv"
import connectDB from "./config/db.js"
dotenv.config();
const app=express()
import cookieParser from "cookie-parser"

//cookies and filemiddleware
app.use(cookieParser())

// morgan middlewares
import morgan from "morgan"
app.use(morgan("tiny"))

// regular middlewares
app.use(express.json())
app.use(express.urlencoded({extended:true}))

// import all routes here
import userRoutes from "./routes/userRoutes.js"

// router middleware
app.use("/api/v1",userRoutes);
export default app;
```<br>
#### → Structure of **index.js**
Here, we listen or run our server at localhost.
```javascript
import app from "./app.js"
const PORT=process.env.PORT||1999

// import {connectDB} from "./config/db.js"

app.listen(PORT,()=>{
console.log(`listening at port http://localhost:${PORT}`)
})
```
<br>
## Workflow

![workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcu52j17e36l24e3qe5o.png)<br>
Basic npm packages to be installed while setting-up new project :

```
npm i express mongoose doting body-parser morgan cors jsonwebtoken bcryptjs validator cookie-parser
```
Before it ends, if you want my node-js-backend-boilerplate it is already created and it is been open sourced under Catalysts Organisation's. <br>
Check Out this GitHub Link for Boilerplate, you can clone this boilerplate for projects : [Click Here](https://github.com/CatalystsReachOut/nodejs-mongodb-backend-boilerplate) <br>
Follow if you find this article helpful. Thank You !