Creating a Blogging Website Using Node.js, JWT Tokens, Express, MongoDB, and Hashing

Rahul BoneyRahul Boney
4 min read

In this tutorial, I will walk through the process of creating a blogging website using Node.js, Express, MongoDB for database storage, JWT tokens for user authentication, and hashing for secure password storage. We'll cover essential backend and frontend aspects, deployment considerations, and more.

Project Setup

Dependencies Installation

Make sure you have Node.js and npm installed. Initialize your project and install necessary dependencies:

npm init -y
npm install express mongoose ejs cookie-parser dotenv bcrypt jsonwebtoken multer

GitHub Repository

You can find the complete code for this project on GitHub: Blogging Website GitHub Repository

Backend Development

Connecting to MongoDB

Ensure MongoDB is installed and running. Connect your Node.js application to MongoDB using Mongoose:

// app.js

const express = require('express');
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const dotenv = require('dotenv');

const userRoute = require('./routes/user');
const blogRoute = require('./routes/blog');

const app = express();
const PORT = process.env.PORT || 8000;

dotenv.config();
mongoose.connect(process.env.MONGO_URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
.then(() => console.log('MongoDB Connected'))
.catch((err) => console.error('MongoDB connection error:', err));

app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static('public'));

// Routes
app.use('/user', userRoute);
app.use('/blog', blogRoute);

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

User Authentication with JWT Tokens

Implement user signup, signin, and authentication using JWT tokens:

// routes/user.js

const express = require('express');
const router = express.Router();
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

// User signup
router.post('/signup', async (req, res) => {
  const { fullName, email, password } = req.body;
  try {
    // Hash password
    const hashedPassword = await bcrypt.hash(password, 10);
    // Create new user
    const newUser = await User.create({
      fullName,
      email,
      password: hashedPassword,
    });
    res.status(201).json({ message: 'User created successfully', user: newUser });
  } catch (error) {
    console.error('Error in user signup:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

// User signin
router.post('/signin', async (req, res) => {
  const { email, password } = req.body;
  try {
    // Find user by email
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    // Compare passwords
    const passwordMatch = await bcrypt.compare(password, user.password);
    if (!passwordMatch) {
      return res.status(401).json({ error: 'Incorrect password' });
    }
    // Generate JWT token
    const token = jwt.sign({ userId: user._id, email: user.email }, process.env.JWT_SECRET, {
      expiresIn: '1h',
    });
    res.cookie('token', token, { httpOnly: true }).json({ message: 'Signin successful', token });
  } catch (error) {
    console.error('Error in user signin:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

module.exports = router;

Frontend Integration

Templating with EJS

Create frontend views using EJS templates for user signup, signin, and blog posts:

<!-- views/signup.ejs -->

<!DOCTYPE html>
<html lang="en">
<head>
  <%- include('./partials/head') %>
  <title>Signup Page</title>
</head>
<body>
  <%- include('./partials/nav') %>
  <div class="container mt-4">
    <form action="/user/signup" method="post">
      <div class="mb-3">
        <label for="fullName" class="form-label">Full Name</label>
        <input type="text" name="fullName" class="form-control" id="fullName" aria-describedby="fullName">
      </div>
      <div class="mb-3">
        <label for="exampleInputEmail1" class="form-label">Email address</label>
        <input type="email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
      </div>
      <div class="mb-3">
        <label for="exampleInputPassword1" class="form-label">Password</label>
        <input name="password" type="password" class="form-control" id="exampleInputPassword1">
      </div>
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>
  <%- include('./partials/scripts') %>
</body>
</html>

Security Measures

Hashing Passwords

Securely hash user passwords using bcrypt before saving them in the database:

// models/User.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt');

const userSchema = new Schema({
  fullName: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
});

// Hash password before saving
userSchema.pre('save', async function (next) {
  const user = this;
  if (!user.isModified('password')) return next();
  try {
    const hashedPassword = await bcrypt.hash(user.password, 10);
    user.password = hashedPassword;
    return next();
  } catch (error) {
    return next(error);
  }
});

module.exports = mongoose.model('User', userSchema);

Deployment and Testing

Deployment on Heroku

Deploy your Node.js application on Heroku, including configuring environment variables and deploying MongoDB databases.

Testing and Debugging

Test backend routes and frontend interactions, and debug common issues such as database connection errors and token authentication problems.


This comprehensive guide covers essential aspects of building a blogging website with Node.js and Express, focusing on backend development, frontend integration using EJS, security measures like password hashing, and deployment considerations. For the complete project code and detailed implementation, visit the GitHub repository: Blogging Website GitHub Repository


0
Subscribe to my newsletter

Read articles from Rahul Boney directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rahul Boney
Rahul Boney

Hey, I'm Rahul Boney, really into Computer Science and Engineering. I love working on backend development, exploring machine learning, and diving into AI. I am always excited about learning and building new things.