Building and Structuring A Node - Js MVC Application - LogRocket Blog
Building and Structuring A Node - Js MVC Application - LogRocket Blog
BLOG
Developers follow many conventions when programming that may or may not
be hard rules, but are often the building blocks of great development projects.
These conventions are used so frequently and adopted so widely because they
are proven to work.
In this tutorial, we’ll learn about the popular architectural pattern Model-
View-Controller (MVC) followed by building and structuring an application in
Node.js using MVC.
Tutorial prerequisites
To follow this tutorial, you will need the following:
Node.js
A MongoDB Atlas account to create our app’s database
Yarn if you are not using npm with Node.js
A text editor, such as Visual Studio Code
What is Model-View-Controller?
MVC is simply a design or architectural pattern used in software engineering.
While this isn’t a hard rule, but this pattern helps developers focus on a
particular aspect of their application, one step at a time.
The main goal of MVC is to split large applications into specific sections that
have their own individual purpose.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 1/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
Model
As the name implies, a model is a design or structure. In the case of MVC, the
model determines how a database is structured, defining a section of the
application that interacts with the database. This is where we will define the
properties of a user that will be store in our database.
The controller accesses the database through the model. You could say that the
model is the heart of the application.
View
The view is where end users interact within the application. Simply put, this is
where all the HTML template files go.
Controller
The controller interacts with the model and serves the response and
functionality to the view. When an end user makes a request, it’s sent to the
controller which interacts with the database.
To understand how to use MVC, we will build a simple login and registration
system with a dashboard that shows users’ information. However, this tutorial
is more about structuring than about the application we are building.
So, open up your terminal in an empty folder and run the following command:
npm init -y
Now for this project, we will need to install some packages to get started:
server
ejs is a templating engine that generates HTML
After this is complete, you should see a node_module folder (this is where all
the packages are downloaded to).
Now create three folders to represent MVC: models , views , and controllers .
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 3/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
After creating the index.js file, go to the package.json file and edit the
scripts like so:
//json
"name": "Dashboard",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"ejs": "^3.1.6",
"express": "^4.17.1",
"mongoose": "^6.0.3",
"passport": "^0.4.1",
Notice how main points to index.js and scripts has develop pointing to
index.js . This means that whenever we run npm run develop from the
command in the root of the application, it will run the entry point, which, in
our case is the index.js file.
Now, let go of the index.js file to create our Express server. Copy and paste
the following code into it:
//js
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 4/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
In line 5, we are now using the listen() method to start up a server that runs
at http://localhost:4111. To confirm that our server is now up and running, run
the following:
It then renders our confirmation that the server is running at port 4111 .
Inside the views folder, create the following files: login.ejs , register.ejs ,
dashboard.ejs , layout.ejs .
The layout.ejs code is included across the .ejs files in the view folder:
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 5/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>MVC</title>
<link
href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
rel="stylesheet" id="bootstrap-css">
<script
src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js">
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
Next, the login.ejs code renders our Login page, as seen below:
Next, create a folder called routes ; this is technically part of the controller,
but it is nice to have all the routing in one, separate folder.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 6/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
res.render("register", {
} );
// For View
res.render("login", {
} );
module.exports = {
registerView,
loginView
};
//js
router.get('/register', registerView);
router.get('/login', loginView);
module.exports = router;
What we are doing here is using the Express router with registerView and
loginView , which are exported from loginController under controllers .
The above two code blocks will not render the Login and Register pages
without updating the index.js file to the following:
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 7/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
//Routes
app.use('/', require('./routes/login'));
Notice that we have set the view engine to use .ejs and defined the root route
to use what’s in login under routes .
Now, you should have your Atlas MongoDB account ready. Go to Atlas and
create a new project and a cluster (use the free option for the sake of this
tutorial).
After creating a cluster, a second page opens, which we can ignore and leave
everything in the default settings. Then, click Create Cluster.
There are few things we need to set to connect the created cluster to our
application.
On the Security tab, select Database Access and create a user by deciding a
username and password. Next, allow users to read and write the database.
Again, on the Security tab, select Network Access, add the IP address, select
ALLOW ACCESS FROM ANYWHERE, and confirm it (this will take about 3
minutes to be active).
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 8/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
Now, go back to the clusters, click Connect, and select Connect your
application
The driver should be Node.js by default, and the version should be 3.6 or later.
The highlighted part in the screenshot below is where your host will be. Note
that yours will be different than mine.
Let’s go ahead and install .dotenv and create the .env file in our root
directory:
Note that this .env file should not be uploaded to your production or even
committed to git; you must include it in your .gitignore file. The .env file
stores virtual environments that must be rebuilt on the server using our
configuration.
Now, let’s go to our index.js entry point to import Mongoose and connect it
to our database. Remember that we installed dotenv , and we must import and
use it along with Mongoose.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 9/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
dotenv.config();
// Mongo DB conncetion
//Routes
app.use('/', require('./routes/login'));
By importing mongoose and dotenv , they immediately call the config method
to enable our connection to read the environment variables and assign their
contents to process.env .
file. Lines 9 to 11 then connect to the database using the Mongoose method,
mongoose.connect() .
Stop the server from your terminal with Ctrl + C and run npm run develop
again. You should get this response that lets us know we did everything
correctly.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 10/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
location: {
type: String,
},
date: {
These are the fields we want to insert into the database whenever a new user
registers through the Registration page. We can store a name, password, email
address, give users a default location of New York, and include a timestamp
when the registration completes.
Registering users
We have created a schema to store our user information in our database inside
the User.js folder within the model folder. To see how this works, let’s make
a POST request on the Registration page.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 11/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
Whenever an end user hits the Register button, a POST request is sent to the
/register route (remember what we did before was a GET request). To make
Next, create a function that handles the POST request to the /register route.
Here, the registerUser function uses data submitted through the form at the
Registration page:
//js
//Confirm Passwords
} else {
//Validation
if (user) {
console.log("email exists");
res.render("register", {
name,
email,
password,
In line 4, we get all the inputs submitted into the form by users:
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 12/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
req.body is an Express API that holds the submitted parameters through the
Lines 8 to 10, check to see if the password fields match; if they do not match, it
logs "Password must match" .
Lines 11 through 21 are an else if statement that only happens if the first two
conditions are false . What it does is check to make sure that multiple users do
not register with the same email address.
By checking the database, if a user exists with the same email address, it will
console log "email exists" and renders the Registration page maintaining the
user’s inputs.
//js
//BodyParsing
app.use(express.urlencoded({extended: false}));
This built-in express middleware gives us the ability to process posted data
and store it in the req.body .
Before we save the user’s information and hashed the password, we must also
check the database to ensure there will never be multiple email addresses so
every user’s email is unique.
Finally, we can export the registerUser module and import it into our
login.js file.
Whenever a user selects the Register button, if everything checks out, the form
creates a user instance in the database and redirects them to the Login page.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 13/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
To ensure our Login page works, we must authenticate users using Passport. If
there is a user in the database, Passport redirects us to a dashboard that
displays the user’s details.
For better organization, let’s create a folder that will handle authentication. In
our root folder create an auth folder, and add passport.js protect.js .
//js
LocalStrategy = require("passport-local").Strategy;
//Load model
passport.use(
//Check customer
.then((user) => {
if (!user) {
console.log("wrong email");
return done();
}
//Match Password
bcrypt.compare(password, user.password, (error, isMatch) => {
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 14/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
Lines 6 through 45 contain the loginCheck function that has the passport
parameter.
Inside the function, we used the LocalStrategy to check the database to see if
there is an existing email already; if there is none, it consoles "wrong email" .
bcrypt.compare() then compares the entered password with the one previously
conditions in the code are false , Passport will serialize and deserialize the
user.
Once confirming the user, Passport creates a session that the user’s browser
maintains for subsequent requests.
Finally, we export the loginCheck . This is what handles our authentication, but
we will need to add some middleware to our index.js file to initialize it.
The middleware requires the passport package and loginCheck from the
./auth/passport.js :
In lines 22 and 23, we used the middleware provided by Passport in our Express
app instance to initialize Passport and maintain a consistent session.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 15/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
//Required
if (!email || !password) {
res.render("login", {
email,
password,
});
} else {
passport.authenticate("local", {
successRedirect: "/dashboard",
failureRedirect: "/login",
failureFlash: true,
})(req, res);
};
With this, we declare a loginUser function. Inside this function, we look for
the email and password entered into our Login page and check to see if the
password or the email field is empty.
If either are empty, we console "Please fill in all the fields" and re-render
the Login page.
Now, if that does not happen, and the email and password are correct, we then
log the user in and redirect to /dashboard , however, we have not created this
route yet.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 16/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
res.render("register", {});
};
//Confirm Passwords
} else {
//Validation
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 17/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//js
if (req.isAuthenticated()) {
return next();
res.redirect('/login');
if (!req.isAuthenticated()) {
return next();
res.redirect('/dashboard');
module.exports = {
protectRoute,
allowIf,
};
The protectRoute function redirects the user to the Login page if they try to
access the dashboard without being authenticated first by logging in through
the Login page.
With the function exported, let’s first add some code to the dashboard.ejs to
define the routes we want to protect.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 18/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
//ejs
<div class="container">
</div>
</div>
<div>
</div>
</body>
</html>
For orderliness, create another controller file. So, in the controllers folder,
create the dashboardController.js file and add the following code:
user: req.user
});
};
module.exports = {
dashboardView,
};
Here, we render the dashboard.ejs as the view here and accessing the
req.user , which is available once there is an active session established by
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 19/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
Then, in our login.js folder under routes , require the protectRoute that we
exported from protect.js under auth :
npm i express-session
After this installs successfully, require it in the index.js file after our express
app instance:
Then, add this before initializing your Passport instance. You can find the full
code here:
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 20/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
app.use(session({
secret:'oneboy',
saveUninitialized: true,
resave: true
}));
This creates a session. And note, according to the Express docs, “Session data
is not saved in the cookie itself, just the session ID. Session data is stored
server-side”.
Now, when we log in with the correct email and password, we should see this:
Conclusion
Congratulations! You have seen this through. I hope you enjoyed and learned a
lot about how to structure and build your next application using the MVC
architectural pattern.
We were able to elucidate on what model, view, and controller mean and
followed this pattern to build and structure a user registration and login
system using Express.js and Passport for authentication. You also saw how we
put all these together with a MongoDB database.
Note that with this structure, you can extend it to whatever application you
want to create, including a full application.
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 21/22
2/18/22, 9:15 AM Building and structuring a Node.js MVC application - LogRocket Blog
LogRocket is like a DVR for web and mobile apps, recording literally everything
that happens while a user interacts with your app. Instead of guessing why
problems happen, you can aggregate and report on problematic network
requests to quickly understand the root cause.
#node
Leave a Reply
https://blog.logrocket.com/building-structuring-node-js-mvc-application/ 22/22