How to Create a Blog(Backend) Using Node.js, Express, MongoDB and Deploy It to AWS EC2

Published on 24 June 2024

Learn how to create a blog application(Backend) using Node.js, Express, MongoDB, and deploy it to AWS EC2. This guide covers everything from setting up your project, creating models and routes, to deploying on a cloud platform.

Introduction

In this tutorial, we will walk through the process of creating a blog application(Backend) using Node.js, Express, and MongoDB, and then deploying it to an AWS EC2 instance. This guide is perfect for developers looking to build a full-stack application and learn about deploying to a cloud service.

Prerequisites

  • Basic knowledge of JavaScript and Node.js
  • An AWS account
  • Node.js and npm installed on your machine
  • Access to MongoDB Atlas

Step 1: Setting Up Your Node.js Project

First, create a new directory for your project and navigate into it:

mkdir blog-app
cd blog-app

Initialize a new Node.js project:

npm init -y

Create the main server file:

mkdir api
touch app.js

Step 2: Setting Up Database

Go over to https://account.mongodb.com/account/login and login, and a create a project for your app.

Give a name to your project and create it.

Now create a cluster as per your needs, here I am choosing a free option i.e. M0

Now we have to create a database user and get the mongodb url to access it on our node app.

Choose Drivers option in Connect to your application

copy the url string and paste it in your node app env files.

//.env

MONGO_URI=mongodb+srv://testuser01:test@123@cluster0.njocipk.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0


Step 3: Setting Up Express

In your app.js file, set up a basic Express server:

// api/app.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
app.use(bodyParser.json());

// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI)
 .then(() => console.log('MongoDB connected'))
 .catch(err => console.log(err));

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
 console.log(`Server running on port ${PORT}`);
});

Step 4: Creating Models and Routes and Controllers

mkdir models 
touch models/blog.model.js

Define the Blog schema:

import mongoose from "mongoose";

const blogSchema = new mongoose.Schema(
  {
    content: {
      type: String,
      required: true,
    },
    title: {
      type: String,
      required: true,
      unique: true,
    },
    slug: {
      type: String,
      required: true,
      unique: true,
    },
    thumbnail: {
      type: String,
      required: true,
    },
    category: {
      type: String,
      required: true,
    },
    isFeatured: {
      type: Boolean,
      default: false,
    },
    summary: {
      type: String,
      required: true,
    },
  },
  { timestamps: true }
);

const Blog = mongoose.model("Blog", blogSchema);

export default Blog;

Next, create a folder called routes and add a blog.route.js file to handle your blog post routes:

import express from "express";
import {
  createBlog,
  getBlogs,
  updateBlog,
} from "../controllers/blog.controller.js";

const router = express.Router();


router.post("/create", createBlog);
router.get("/get/all", getBlogs);
router.get("/get/:slug", getSingleBlog);
router.put("/update/:slug", verifyToken, updateBlog);

export default router;

Next, create a folder called controllers and add a blog.controller.js file to handle your blog functions:

import Blog from "../models/blog.model.js";

export const createBlog = async (req, res, next) => {
  if (!req.body.title || !req.body.content) {
    return next(errorHandler(400, "Please provide all required fields"));
  }

  const newBlog = new Blog(req.body);

  try {
    const savedBlog = await newBlog.save();
    res.status(201).json(savedBlog);
  } catch (error) {
    next(error);
  }
};


export const getBlogs = async (req, res, next) => {
  try {
    const allBlogs = await Blog.find({});
    const dateDescBlogs = allBlogs.sort((a, b) => {
      return new Date(b.createdAt) - new Date(a.createdAt);
    });
    res.status(201).json(dateDescBlogs);
  } catch (error) {
    next(error);
  }
};

export const getSingleBlog = async (req, res, next) => {
  try {
    const singleBlog = await Blog.findOne({ slug: req.params.slug });
    res.status(201).json(singleBlog);
  } catch (error) {
    next(error);
  }
};


export const updateBlog = async (req, res, next) => {
  try {
    const updatedBlog = await Blog.findOneAndUpdate(
      { slug: req.params.slug },
      {
        $set: {
          title: req.body.title,
          status: req.body.status,
          summary: req.body.summary,
          slug: req.body.slug,
          category: req.body.category,
          isFeatured: req.body.isFeatured,
          thumbnail: req.body.thumbnail,
          content: req.body.content,
        },
      },
      {
        new: true,
      }
    );
    res.status(200).json(updatedBlog._doc);
  } catch (error) {
    next(error);
  }
};

Add the routes to your app.js file, finally app.js will look like:

import dotenv from "dotenv";
import express from "express";
import mongoose from "mongoose";
import cors from "cors";
import bodyParser from "body-parser";

import blogRoutes from "./routes/blog.route.js";


dotenv.config();

// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI)
 .then(() => console.log('MongoDB connected'))
 .catch(err => console.log(err));

const app = express();
const PORT = 5000;

app.use(express.json());
app.use(cors());


app.use(bodyParser.json());

app.listen(PORT, () => {
  console.log("Server is running on port", PORT);
});

app.use("/api/blog", blogRoutes);

Step 5: Run the server

node api/app.js

Step 6: Access Your Blog Locally

Open a browser and navigate to http://localhost:5000 to see your blog posts.

Step 7: Deploying to AWS EC2

1. Launch an EC2 Instance

  1. Go to the AWS Management Console.
  2. Navigate to EC2 and launch a new instance.
  3. Choose an Amazon Machine Image (AMI) like Ubuntu.
  4. Select an instance type, such as t2.micro (which is free tier eligible).
  5. Configure instance details and add storage as needed.
  6. Add a security group rule to allow HTTP and SSH access.
  7. Review and launch the instance.

2. Connect to Your EC2 Instance

Once your instance is running, connect to it using SSH:

ssh -i path/to/your-key.pem ubuntu@your-ec2-public-ip

3. Set Up Your Environment

Update your package list and install Node.js and npm:

sudo apt update
sudo apt install nodejs npm

4. Deploy Your Application

Clone your project repository from GitHub (or upload your files directly):

git clone https://github.com/yourusername/your-repo.git
cd your-repo

Install your project dependencies:

npm install

Set up your environment variables. Create a .env file and add your MongoDB URI:

touch .env
nano .env

Add the following to your .env file:

MONGO_URI=mongodb+srv://testuser01:test@123@cluster0.njocipk.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0

Step 8: Access Your Blog Online

Open a browser and navigate to http://your-ec2-public-ip:5000/posts to see your blog posts.

Conclusion

By following these steps, you have created a full-stack blog application using Node.js, Express, and MongoDB, and deployed it to an AWS EC2 instance. This setup allows you to manage and deploy your application efficiently, leveraging the power of cloud computing.