Android chat app in Kotlin and Node JS

We created a chat application in native Android using Kotlin and Node JS. We have used Mongo DB as a database.

Modern and professional UI

End-to-end encryption

Usually, we use encryption but on server side. It has a security issue i.e. plain messages are transmitted through a network that can be read or altered in-transit.

But in this app, we have implemented end-to-end encryption means the encryption and decryption is done on client side rather than on server side. Client will encrypt the message and send it to the server. Server will send the encrypted message to the receiver and the receiver client will do the decryption. So even the server will not be able to read your messages.

We will be using the AES-256-bit length key to generate secret keys. All messages are sent to the server after encryption. So data will remain safe in-transit.

Voice notes

Sending voice notes is a quick way to send messages especially when you are in places when you are in hurry. Instead of typing the message which might cause spelling mistake, you can simply record your audio and send it directly to the receiver inside the app. No need to record the audio from a separate app and attach the audio in a message. You can also listen to your sent or received voice notes within the app.

If you use WhatsApp, you already know how voice notes work. You will learn how to record audio from your android phone and save it in your phone’s storage. Once stored, we will send that MP3 file to the Node JS server. The server will save the file. The user will be able to play that audio from the URL.

All contacts

We are using android contact’s API to fetch all the contacts. So you will learn how to get runtime contacts permission in android.

Private chat

The user can chat with any of his contact numbers as long as the receiver is a registered user.

Chat attachments

Users can attach files in chat messages as well. Images and videos are not compressed at all. So the receiver will see the image in its original quality.

Search contacts

Group chat

Users can chat in groups. Create as many groups as you want. Add members to them and start chatting. What makes it different from other chat apps ? First, it does not allow anyone to add you to a group. You will be invited. You will only start receiving the group notifications when you accept the invitation. Second, this app displays a list of all groups separately. So you can know in which groups you are currently in.

Share status that disappears after 24 hours

In this tutorial, you will:

  • Be able to share your status with all your contacts
  • Exclude some contacts from viewing your status
  • Create multiple lists (e.g. friends, family, colleagues, etc.) so you won’t have to select the contacts each time you upload a status
  • See contacts who have viewed your status/story
  • Download the image or video of status

Seen/unseen messages (blue ticks)

In this part, you will learn how to:

  • Install sockets in android
  • Connect android sockets with the Node JS server
  • Get real-time events on new message
  • Mark messages as read and un-read
  • Get bluetick (like WhatsApp) when the user sees your message

User profile

Search messages

Learn how to apply case in-sensitive sub-string search on all the messages in a chat with any of your contact. You can write any part of text of message and the app will show you the messages that matched your searched string.

Although the messages are end-to-end encrypted, which means that the server will not be able to apply search because server can’t read your messages. But we still found a way to apply search on end-to-end encrypted messages.

How to install

Our TrustPilot Reviews

TrustPilot-reviews

Ecommerce website in MEVN stack

It is a single-page ecommerce website developed in Vue JS. Vue JS is an open-source Javascript framework specifically built to design user interfaces and is widely used for creating single-page applications.

Node JS is a Javascript run-time environment developed for creating the backend of applications. Its framework Express is widely used for creating APIs. It is built to create scalable applications.

Mongo DB is a no-SQL database. It is a non-relational database system. It is easily scalable because the data is loosely coupled.

FeaturesFreePremium $100
Product management (admin panel)YesYes
Product listingYesYes
Product detailYesYes
Shopping cartYesYes
Checkout (PayPal & Stripe)YesYes
Order management (admin panel)YesYes
Order detailYesYes
Product specificationsYesYes
Stock managementYesYes
Search and sortYesYes
New order emailYesYes
Product reviewsNoYes
Shipping charges by countryNoYes
Product image compressionNoYes
Realtime chat between users and adminNoYes

Following is the feature list of this project:

  • Product management (admin panel)
  • Product listing
  • Product detail
  • Shopping cart
  • Checkout (PayPal & Stripe)
  • Order management (admin panel)
  • Order detail
  • Product specifications
  • Stock management
  • Product reviews
  • Search and sort
  • Shipping charges by country
  • Email to admin whenever a new order is placed
  • Product image compression
  • Realtime chat between users and admin

Add product

Admin will be able to add products. He will enter the name of the product. Add a little description of the product. And set the price of the product. The price will be in dollars. Along with them, the admin can upload one or more images of the product.

Product listing

Users will see the products added by the admin on their home page. The latest products are displayed first. Along with each product, a button will be displayed to view the detail of the product.

Product detail

Users can view the detail of the product. If the product contains more than one image, then it will be displayed as a beautiful slider. From this page, users will also be able to add products to the cart. If the product is already added to the cart, then he will be able to remove it from the cart.

Shopping cart

Users can add the product to the cart. From the cart’s page, he will be able to adjust the quantity of the product. There will be multiple products in the cart and you can set the quantity of each product separately. You will also see your total bill as soon as you change the quantity of any product added to the cart.

Checkout (Stripe & PayPal)

After adding the products to the cart and setting each product’s quantity, the user can go to the checkout page. Here, he can either pay via Stripe or PayPal. Both payment methods accept debit and master cards securely. When the user made the payment, his payment is verified from the server. If verified, then a new order will be created in the database.

Order management

Whenever a user made a payment via Stripe or PayPal, an order will be created. All orders will be displayed on the admin panel ordered by latest to oldest. By default, the status of the order is “Processing”. But admin can change the status of the order to “Completed” when the product is delivered to the customer.

Admin will also be able to view the total amount of the order, the payment method customer has used, and the user’s shipping details.

Order detail

Admin can view all the products that were included in each order. He can manually verify the payment by clicking the payment method. If he clicks “Stripe”, he will be redirected to the Stripe payments page. If he clicks “PayPal”, then he will be redirected to the PayPal business page. Admin can check the name, email, and phone of the user and also his shipping address.

Product specifications

Admin can add the specifications of each product and the user will be able to see it on the product detail page.

Stock management

Admin can set the number of units in stock for each product. When the user makes an order, then the number of units he has selected will be subtracted.

Product reviews

User can give reviews on a product and it will be displayed to all users who visit that product. Admin will have the ability to remove any review, for example, spamming, etc.

Search and sort

Users can search by product by its name, description, category, or specifications. Users can also sort the products by date or by price.

Shipping charges by country

Admin can set the shipping charges by each country because, in a global eCommerce website, users place orders from all over the world. For example, if your store is located in USA and someone places an order from the UK. Then you charge the shipping fee differently than other countries.

Email to admin whenever a new order is placed

Admin will receive an email whenever a new order has been placed by the user.

Product image compression

Now you can compress the product images from the admin panel. The 3 MB image can be reduced to just 182 KB and the image will still be of great quality.

Realtime chat between users and admin

Users will be able to have a chat with the admin to know more about a product before placing an order. I believe every eCommerce website should have this feature.

We are constantly updating this project and adding more features and enhancements to it. Following are all the builds that are released till today.

  • In the very first release, we build the basic E-commerce version where the admin can add products and users can see them. Add them to carts and order them. We also added Stripe and PayPal payment methods.
  • In the second release, we added more features. Allowing users to give reviews about a product. Allowing admin to charge a different shipping fee for each country and many more.
  • In the third release, we added functionality to compress product images and to have real-time chat between users and admin.

Free version

https://github.com/adnanafzal565/ecommerce-mevn-stack

Deploy Node JS app on VPS or Dedicated server

In this article, we are going to teach you how you can deploy the Node JS app on a VPS (Virtual Private Server) or a dedicated server. Make sure you have Node JS, NPM (Node Package Manager), and PM2 (Process Manager) installed, you can run the following commands to see if they are installed.

node -v
npm -v
pm2

If any of them is not installed on your server, you can simply chat with your hosting provider’s customer support center or open a ticket and ask them to install these for you. The main thing you are going to need for deployment is pm2.

Install Node JS

To install specific version of Node JS, first you need to install NVM (Node Version Manager).

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

Then you need to reload your shell configurations.

source ~/.bashrc

You can verify your installation of NVM by running the following command.

nvm -v

It will show you your NVM version (0.39.5 at the time of writing this). Then run the following command to list all available Node JS versions.

nvm ls-remote

You can install the specific version of Node JS by running:

nvm install 22.11.0

Here, 22.11.0 is the latest LTS version at the time of writing this post. You can set it accordingly. In order to make your NVM to use the installed version by default, you can run the following 2 commands.

nvm default 22.11.0
nvm alias default 22.11.0

If everything goes well, you can run the following command to verify that the Node JS has been successfully installed in your VPS or dedicated server.

node -v

Install PM2 (Process Manager)

If pm2 is not installed in your server, you can install is by running the following command:

npm install -g pm2

Creating a Node JS server

First, create a sub-domain for example “node.adnan-tech.com”. It will also create a directory for this sub-domain. Then create a simple Node JS app in it by running the following command in your cPanel terminal:

npm init

Press Enter key for all questions to set the default values. Then install the following modules:

npm install express http cors express-formidable socket.io

Inside the directory created for the sub-domain, create a file named “server.js” and write the following code in it:

server.js

const express = require("express")
const app = express()

const cors = require("cors")
app.use(cors())

const expressFormidable = require("express-formidable")
app.use(expressFormidable())

const http = require("http").createServer(app)
const socketIO = require("socket.io")(http, {
	cors: {
		origin: "*"
	}
})

const port = process.env.PORT || 3000

http.listen(port, function () {
	console.log("Server started at port: " + port)

	socketIO.on("connection", function (socket) {
		console.log("User connected: " + socket.id)

		// [listen events here]
	})
	
	app.get("/", function (request, result) {
	    result.send("Hello world !")
	})
	
	// [create API here]
})

Then you need to tell your Node JS app that you will be using server.js as the main file. So open your package.json file and set the main key’s value to “server.js” as follows:

package.json

"main": "server.js",

Deploy the Node JS app

Now to start the server, first, open your “Terminal” from cPanel, and go to your subdomain by running the command:

cd yoursubdomain.com

Or whatever your subdomain path is. Then run the following command to start the server:

pm2 start server.js --name "Name of your app" --watch

–name is used to set a specific name for your app.

–watch is used to automatically restart the server if there is any change in the server.js file.

List all processes using pm2

You can view the list of all processed from the command:

pm2 list

If the write the URL https://yoursubdomain:3000/ in the browser, you will see the text “Hello world”. It means your Node JS server is successfully deployed on your VPS or dedicated server.

Create an API in Node JS

Now write the following code to create an API in the [create API here] section:

app.post("/myAPI", function (request, result) {
    const name = request.fields.name
    
    result.json({
        status: "success",
        message: "API has been called.",
        data: "Your name is " + name
    })
})

Then create an index.html file anywhere in your domain and write the following code to it to call an AJAX to this Node JS server.

index.html

<script>
	const ajax = new XMLHttpRequest()
	ajax.open("POST", "https://yoursubdomain:3000/myAPI", true)

	ajax.onreadystatechange = function () {
		if (this.readyState == 4) {
			if (this.status == 200) {
				console.log(this.responseText)
			}
		}
	}

	const formData = new FormData()
	formData.append("name", "Adnan")
	ajax.send(formData)
</script>

Open your browser console tab and you will see the message “Adnan”. Try changing the value in the “name” field in the formData object and refresh the page, you will now see your updated value.

Socket IO

You can also connect sockets to this Node JS server. In your index.html file, first, include the socket IO JS library using CDN:

<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>

Then write the following Javascript code to connect the client with the server:

<script>
	const socketIO = io("https://yoursubdomain:3000")
</script>

After that, emit a simple event to the server:

// index.html

socketIO.emit("newEvent", { name: "Adnan" })

Then in your server.js, write the following code in place of the [listen events here] section:

// server.js

socket.on("newEvent", function (data) {
	socket.emit("newEvent", data)
})

And finally, on your client side, you need to listen to this event and display a message in the browser console:

// index.html

socketIO.on("newEvent", function (data) {
	console.log(data)
})

Refresh your page now and open your browser console. You will now see an object in the console. It means that your Node JS server’s sockets are running fine.

Stop the pm2 process

By default, the pm2 process will keep on running forever. If you want to stop the process, you can simply enter the following command in your cPanel terminal:

pm2 stop "Name of your app"

Run pm2 list and you will now see the status of your process as stopped.

Remove the pm2 process

Similarly, you can remove the pm2 process by running the following command:

pm2 delete "Name of your app"

Run pm2 list and you will no longer see your process in the list.

So that’s how you can deploy a Node JS app on your VPS or dedicated server. Check our tutorial to deploy Node JS app on the Heroku server. If you face any problems in following this, kindly do let me know.

How to create nested modules – Node JS

In this article, we are going to teach you, how you can have nested modules in your Node JS project. Nested modules help in splitting a large code-base into smaller files. This helps in debugging and scaling easily.

Video tutorial

Let’s say that you want to access the following URL:

http://localhost:3000/users/social

You want to have a “users” module where all user code will go. And you want the user’s module to be further divided into “social” module where all the code for user’s social networks will go, for example.

If you do not know how to create and set up a Node JS application, please check our this tutorial first.

So we will start by creating a user module. Create a new folder named “modules” at the root of your project. Then in this folder, create a file named “users.js”. The following code will go in the users.js file.

const express = require("express")

// [include social.js module]

module.exports = {
	init: function (app) {
		const userRouter = express.Router()

		userRouter.get("/", function (request, result) {
			result.send("Inside users.js")
		})

		app.use("/users", userRouter)

		// [call init method of social.js here]
	}
}

It creates a router object, named userRouter, from the express object. Then it tells the app to use this userRouter object for every route starting from “/users” in the URL. The init function accepts an app object which we will send from our main “server.js” file.

So go to your main “server.js” file and include the users module in it by writing the following line at the top.

const users = require("./modules/users")

const express = require("express")
const app = express()

Then, we need to call the init function of it and pass the app instance to it.

users.init(app)

If you access the following URL now, you will see a message “Inside users.js” in the browser:

http://localhost:3000/users

Now we need to create another file named “social.js” inside modules folder. The following will be the code for social.js file:

const express = require("express")

module.exports = {
	init: function (userRouter) {
		const socialRouter = express.Router()

		socialRouter.get("/", function (request, result) {
			result.send("Inside social.js")
		})

		userRouter.use("/social", socialRouter)
	}
}

This module’s init method accepts userRouter as an argument that we had created in our “users.js” file. And it is using that userRouter object instead of app object because this module will be used only when the “/social” path is appended after the “/users” path.

The final thing you need to do is to call the init method of the “social.js” file inside our “users.js” file. So go to your “users.js” file and first include the social module in it. Write the following line in the [include social.js module] section:

const social = require("./social")

Then write the following code in the [call init method of social.js here] section:

social.init(userRouter)

So if you access the following URL now, you will be able to see “Inside social.js” in your browser.

http://localhost:3000/users/social

We created an E-commerce application in Node JS and Mongo DB where we used nested modules to have admin > products and orders. You can check that project from here.

So that’s how you can have nested modules in Node JS express framework. If you face any problems in following this, kindly do let me know.

Source code – How to create nested modules in Node JS

[wpdm_package id=’1736′]

Upload multiple images in Node JS and Mongo DB

In this article, we are going to teach you, how you can upload multiple images in Node JS and Mongo DB.

Video tutorial:

Initializing the project

First, you need to create an empty folder and open a command prompt or terminal in it. Then run the following command in that CMD:

> npm init

It will ask multiple questions, just press enter to set the default values.

Then you need to install the express and HTTP modules. So run the following command:

> npm install express http

Then create a file named server.js and write the following code in it:

const express = require("express")
const app = express()
const http = require("http").createServer(app)

// [include Mongo DB]

// [set view engine]

// [Express formidable and FS module]

// [recursive function to upload images]

const port = process.env.PORT || 3000
http.listen(port, function () {
    console.log("Server started running at port: " + port)

    // [connect Mongo DB]
})

If you open your CMD, you will see the message “Server started running at port: 3000”.

You can check your project from the URL: http://localhost:3000/

Installing Mongo DB

To install the Mongo DB module, first, run the following command in your terminal:

> npm install mongodb

Then include the Mongo DB module in your server.js file in the [include Mongo DB] section:

const mongoClient = require("mongodb").MongoClient

Then connect with the database by writing the following code in the [connect Mongo DB] section:

mongoClient.connect("mongodb://localhost:27017", async function (error, client) {
    if (error) {
        console.error(error)
        return
    }

    const db = client.db("multiple_images_upload")
    console.log("Database connected")

    // [routes]
})

To learn more about Mongo DB, check our tutorials on Mongo DB here.

Display form to upload multiple images

To display an HTML file in Node JS, we need to install a module named EJS. You can install it by running the following command:

> npm install ejs

Then we need to tell our app to use the EJS as the templating engine. So write the following code in the [set view engine] section:

app.set("view engine", "ejs")

Then create a GET route in the [routes] section of server.js file:

app.get("/", async function (request, result) {
    result.render("home")
})

Then create a folder named views and inside this folder create a new file named home.ejs. In this file, we will create a form with an input type file.

<!-- home.ejs -->

<form onsubmit="uploadImages()" enctype="multipart/form-data">
    <input type="file" multiple accept="image/*" name="images" required />

    <input type="submit" value="Upload images" />
</form>

multiple: This will allow multiple file uploads.

accept=”image/*”: This allows only image files to be uploaded.

Then we will create this Javascript function to call an AJAX.

<script>
    function uploadImages() {
        // prevent the form from reloading the page
        event.preventDefault()

        // get form tag
        const form = event.target

        // create form data object from <form>
        const formData = new FormData(form)

        // create AJAX object
        const ajax = new XMLHttpRequest()

        // 1st parameter = method, GET/POST
        // 2nd parameter = path to server file
        // 3rd parameter = asynchronous
        ajax.open("POST", "/uploadImages", true)

        // when status of request changes
        ajax.onreadystatechange = function () {
            // operation is completed
            if (this.readyState == 4) {
                // response from server is okay
                if (this.status == 200) {
                    // response from server
                    console.log(this.responseText)
                }
            }
        }

        // send AJAX request
        ajax.send(formData)
    }
</script>

Comments have been added with each line for the explanation.

Upload multiple images in Node JS

To handle the form data object, we must first install the express-formidable and fs modules. FS stands for File System. To install these modules, run the following command:

> npm install express-formidable fs

Then you need to include these modules in your server.js file, in the [Express formidable and FS module] section:

const formidable = require("express-formidable")
app.use(formidable({
    multiples: true, // request.files to be arrays of files
}))

const fileSystem = require("fs")
app.use("/uploads", express.static(__dirname + "/uploads"))

Then create a folder named uploads at the root of your project.

After that, create the following POST route to handle that AJAX request:

app.post("/uploadImages", async function (request, result) {
    const images = []
    if (Array.isArray(request.files.images)) {
        for (let a = 0; a < request.files.images.length; a++) {
            images.push(request.files.images[a])
        }
    } else {
        images.push(request.files.images)
    }

    callbackFileUpload(images, 0, [], async function (savedPaths) {
        await db.collection("images").insertOne({
            images: savedPaths
        })

        result.send("Images has been uploaded.")
    })
})

To upload images, we will be using a recursive function. So create a recursive function in the [recursive function to upload images] section:

function callbackFileUpload(images, index, savedPaths = [], success = null) {
	const self = this

	if (images.length > index) {

		fileSystem.readFile(images[index].path, function (error, data) {
			if (error) {
				console.error(error)
				return
			}

			const filePath = "uploads/" + new Date().getTime() + "-" + images[index].name
			
			fileSystem.writeFile(filePath, data, async function (error) {
				if (error) {
					console.error(error)
					return
				}

				savedPaths.push(filePath)

				if (index == (images.length - 1)) {
					success(savedPaths)
				} else {
					index++
					callbackFileUpload(images, index, savedPaths, success)
				}
			})

			fileSystem.unlink(images[index].path, function (error) {
				if (error) {
					console.error(error)
					return
				}
			})
		})
	} else {
		success(savedPaths)
	}
}

Run the project now and you see a form with an input file and a submit button. Select multiple images from your computer and hit submit. Once submitted, you will see your uploaded images in the “uploads” folder and a new document will be created in the Mongo DB images collection.

Show uploaded images

Now we need to show all uploaded images. First, change your home route in server.js to the following:

app.get("/", async function (request, result) {
    const images = await db.collection("images").find({}).toArray()
    result.render("home", {
        images: images.length > 0 ? images[0].images : []
    })
})

This will pass all the images from the first document of images collection to the home file. Now go to your home.ejs and write the following for loop to display all images:

<%for (let a = 0; a < images.length; a++) { %>
    <img src="<%= images[a] %>" style="width: 100%;" />
<% } %>

Refresh the page now and you will be able to view all uploaded images.

If you face any problem in this, please do not hesitate to get in touch with me.

To run the following downloaded files, run the following command in your terminal first:

> npm update

[wpdm_package id=’1727′]

Compress image in Node JS

In this tutorial, we are going to teach you, how you can compress image in Node JS. You can download and install Node JS from their official site.

Video tutorial: Compress image in Node JS

First, create a new folder. Open CMD in it. And run the following commands:

> npm init
> npm install express http

Then, create a file named “server.js” and write the following code in it:

const express = require("express")
const app = express()
const http = require("http").createServer(app)

// [other modules]

const port = process.env.PORT || 3000

http.listen(port, function () {
	console.log("Server started running at port: " + port)

	// [post route goes here]

	// [get route goes here]
})

Then run the following commands in your terminal:

> npm install -g nodemon
> nodemon server.js

You will see a message saying the “Server started running at port: 3000”. You can access your server from the following URL:

http://localhost:3000

Now, we need to install the module for displaying views. And to get input from form fields. So, install the following modules:

> npm install ejs fs express-formidable

EJS module is used for displaying the HTML files. FS stands for File System, this module is used to handle files. And “express-formidable” is used for getting values from the input field. Make sure to run the “nodemon server.js” command again.

Install compress image module in Node JS

To install a module to compress image in Node JS, you need to run the following command in your terminal:

> npm install pngquant-bin@6.0.1 gifsicle@5.2.1 compress-images fs

Then, we need to include those modules in our project. So write the following lines in the [other modules] section:

const compressImages = require("compress-images")
const formidable = require("express-formidable")
app.use(formidable())

const fileSystem = require("fs")
app.set("view engine", "ejs")

Now, write the following lines in the [get route goes here] section:

app.get("/", function (request, result) {
	result.render("index")
})

After that, you need to create a folder named “views” at the root of your project. And in that folder, create a file named “index.ejs”. Following will be the code of “index.ejs”:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<title>Compress image</title>
	</head>

	<body>
		<form method="POST" action="/compressImage" enctype="multipart/form-data">
			<input type="file" name="image" accept="image/*" required />
			<input type="submit" value="Compress image" />
		</form>
	</body>
</html>

It will display a simple HTML form with an input field and a submit button. Then, you need to create a POST route that will handle this request. The following code goes in the [post route goes here] section of the “server.js” file:

app.post("/compressImage", function (request, result) {
    const image = request.files.image
    if (image.size > 0) {

        if (image.type == "image/png" || image.type == "image/jpeg") {
            fileSystem.readFile(image.path, function (error, data) {
                if (error) throw error

                const filePath = "temp-uploads/" + (new Date().getTime()) + "-" + image.name
                const compressedFilePath = "uploads/"
                const compression = 60
                
                fileSystem.writeFile(filePath, data, async function (error) {
                    if (error) throw error
                    
                    compressImages(filePath, compressedFilePath, { compress_force: false, statistic: true, autoupdate: true }, false,
                        { jpg: { engine: "mozjpeg", command: ["-quality", compression] } },
                        { png: { engine: "pngquant", command: ["--quality=" + compression + "-" + compression, "-o"] } },
                        { svg: { engine: "svgo", command: "--multipass" } },
                        { gif: { engine: "gifsicle", command: ["--colors", "64", "--use-col=web"] } },
                        async function (error, completed, statistic) {
                            console.log("-------------")
                            console.log(error)
                            console.log(completed)
                            console.log(statistic)
                            console.log("-------------")

                            fileSystem.unlink(filePath, function (error) {
                                if (error) throw error
                            })
                        }
                    )

                    result.send("File has been compressed and saved.")
                })

                fileSystem.unlink(image.path, function (error) {
                    if (error) throw error
                })
            })
        } else {
            result.send("Please select an image")
        }
    } else {
        result.send("Please select an image")
    }
})

The last thing you need to do is to create two folders named “uploads” and “temp-uploads” at the root of your project. Here, all compressed images will be stored.

This will compress the image up to 60%. You can now try to select an image from the input file and hit “Compress image”. You will see a success message if everything goes right. And you will see your compressed image in the “uploads” folder.

Real-world example

We implemented this compression in one of our projects, so you can get the real-world example of image compression in Node JS.

So that’s how you can compress an image in Node JS. If you face any problems in following this, kindly do let us know.

Download source code

[wpdm_package id=’1704′]

Single page application in MEVN stack – Realtime chat

In this article, we are going to provide you with a free course to develop a full-fledged real-time chat app in MEVN (MongoDB, Express, Vue JS, and Node JS) Stack. Here M stands for MongoDB which we have used as a database. E stands for Express which is a Node JS framework. V stands for Vue JS which will be our front end. We will be creating a single-page application in Vue JS. And N stands for Node JS which will be our backend.

You can download Node JS from here. And Mongo DB from their official site.

FeaturesFreePremium $100
Sign upYesYes
Login/logoutYesYes
Add contactsYesYes
Private chatYesYes
Message encryptionYesYes
Chat with attachmentYesYes
Realtime chatYesYes
Email verificationNoYes
Reset passwordNoYes
User profileNoYes
Chat with emojisNoYes
Bookmark messagesNoYes
Copy messageNoYes
Archive chat with passwordNoYes
Group chatNoYes
Notifications pageNoYes
Customer supportNoYes

We will do the deployment of this app on live servers. You can find the link to all the tutorials of this series here. Following are the topics we have covered in this series.

Installation of Node JS server

In the very first tutorial, we have done the installation of the Node JS server. We also connect our Node JS server with MongoDB. You can find the tutorial here.

Setup Vue JS CLI – A single page application

Then we set up our Vue JS app using CLI. We used Vue JS CLI because we will be creating a single page application. We will be using Vue 3. Right now, we will be using the app on the local server. But once it is done, we will teach you how you can create a production build of it. And also how you can make it live on your website. This tutorial can be found here.

Routing for single page application

As this is a single page application, so we will be doing routing using Vue components. You can learn how to implement routing in a single page Vue JS app from this tutorial.

Hello world

In this part, we will learn how to integrate Bootstrap into your Vue app. So you can design the theme as per your choice. We also show you how you can create header and footer layouts in Vue JS. The header and footer will be displayed on each page. For the header, we will be creating a simple Bootstrap navbar. And for the footer, we will simply be displaying copyright text and the current year dynamically.

Registration

You will learn how to display a form using Vue JS. Sends the form values to the Node JS server. And how Node JS can save the data in the MongoDB database. You will also learn how to check if certain data exists in MongoDB or not. Moreover, you will also learn how to encrypt the passwords before saving them in MongoDB. So even if your database gets stolen, your user’s passwords will remain unknown to the hacker.

One more thing you will learn in this part is how to deal with CORS (Cross-Origin Resource Sharing) errors in the Node JS server.

Email verification

After successful registration, an email will be sent to the user’s email address. That email will have the verification code. And the user will be redirected to a page where he can enter his verification code.

He will not be able to log in until he verifies his email address.

Login

In this part, we do the authentication. You will learn how to generate JWT (JSON Web Tokens) and how to store them in local storage for future usage. You will also learn how to validate the encrypted passwords saved in MongoDB while authenticating.

Reset Password

If a user forgets his password, he can reset it. He just needs to enter his email address. An email will be sent to him with a link to reset the password. When he clicks that link, he will be redirected to a page where he can enter his new password.

Get logged-in user’s data

We will learn how to call AJAX with headers in Vue JS. How Node JS server read the headers? And how to create middleware in Node JS.

Logout

We will teach you how to log out as a user from MongoDB and from the Vue JS client app. We will remove the JWT token we create in the login part.

Contacts

To chat with people, we need to add them to our contacts. We will be creating separate components in the Vue JS app for adding and displaying all contacts. We will also be creating a new module in the Node JS server. You will learn how to insert data in a nested array in MongoDB.

We will be calling AJAX requests using Axios in Vue JS. While deleting a contact, you will learn how to ask for confirmation using sweet alert dialogs.

You will also learn how to remove an element from a nested array in MongoDB.

Chat with attachments

This is the main module of this app. We advise you to please put more focus on this part. It teaches you how to import CSS in specific Vue components only. How to send input type file from the Vue JS app to the Node JS server. How Node JS saves files on the server.

Encryption and Decryption

We are saving messages in MongoDB in encrypted form. While fetching the messages, we are again decrypting the messages back to their original state. Even if someone has access to your database, he will not be able to read your messages. Because he does not have the key. The key will only be stored on the Node JS server.

You can see the messages are fully encrypted. On the home page, where we are displaying all user’s contacts, we will also be displaying unread messages from each contact.

Attachments uploaded with messages are also protected from direct URL access. So we will show you how you can convert a file in base64 string using Node JS. And download them to your system using the Vue JS app.

Realtime chat using Socket IO

Chat will be real-time. Meaning users do not have to refresh the page to see new messages. He will automatically receive a notification. If the chat is opened, then the incoming message will be appended automatically.

We have “load more” functionality. This means that we will only show 10 messages in each AJAX call. To get the previous 10 messages, the user will click on that button and we will fetch 10 more messages. So you will learn pagination using Node JS and Mongo DB too.

Deploy Node JS, Mongo DB, and Vue JS apps

We will be deploying our Node JS server on Heroku. You can check our Heroku guide here. We will be deploying MongoDB on mongodb.com. And we will be deploying our Vue JS app on any hosting provider we choose. For example, a2hosting, Bluehost, Siteground, etc. We will create a production-ready build of our Vue JS app and upload it on our live server.

However, you might face some problems going live. That’s why we have written a detailed complete tutorial on the deployment on all these 3 platforms.

Search Contact

You can search your contacts by their email address. Searching with their email address points you to the right person. Because multiple people can have the same name. But email is unique in the entire “users” collection in MongoDB.

Group chat

Previously we discussed private chat. In this tutorial series, we also cover the group chat feature. You will be able to create groups. Add members to the groups. You will be sending an invitation to the members to join the group. The other person can accept your request to join the group or can ignore it.

Any member can leave the group anytime he wants. But this is not the case for admins. For the admin to leave the group, he must first assign someone else to the admin of the group. The other person must be a member of the group. After assigning someone else as an admin, he can easily leave the group.

People who are not members or the admin of the group, cannot send or view the messages in the group chat.

The chat in the group is also real-time. All the other members of the group will get a notification when someone sends a message. If they have opened the group, then the new message will automatically get appended at the end of the chat.

Group chat is also end-to-end encrypted.

And same as we did for private chat, we are displaying several unread messages from a group on the page where we are displaying all groups.

Emojis

In chat, you can also send emojis to the recipient. Emojis are also encrypted.

Bookmark message

You can also bookmark your favorite messages. This way, you can always see your bookmarked messages whenever you want. You can bookmark your messages as well.

Copy message

If someone sends you a lengthy message, like an essay. You can copy the whole message with a single click.

Archive chat with password

  • You can archive your private chat with a password.
  • Once archived, no one will be able to view the chat.
  • To view the chat, you must provide the correct password.
  • You can remove the password by simply entering the correct password.
  • Archived chats cannot be deleted. You must first un-archive the chat, then delete it.

Re-designed

I re-designed the website into a beautiful template. That’s how it looks now.

So you will be learning to create a full-stack chat app from scratch using Node JS, Mongo DB, and Vue JS. Again, you can find the tutorial for the complete series here. Enjoy!

Free version

https://github.com/adnanafzal565/spa-chat-app-mevn

Our Trustpilot reviews

Encrypt and Decrypt Strings using Node JS and Mongo DB

In this tutorial, we are going to teach you, how you can encrypt and decrypt the strings using Node JS and Mongo DB. The encrypted strings will be saved in the database and upon retrieval will be decrypted.

Setup the Project

First, create an empty folder and open a command prompt in it. Then run the following commands in it one by one:

npm init
npm install express http mongodb crypto ejs
npm install -g nodemon
nodemon server.js

crypto module will be used to encrypt and decrypt the strings. ejs module will be used to render HTML files. Then create a file named server.js at the root of folder. Open server.js file and write the following code in it:

// initialize express JS
const express = require("express");
const app = express();

// create HTTP server
const http = require("http").createServer(app);

// [include Mongo DB module here]

// start the server
http.listen(process.env.PORT || 3000, function () {
    console.log("Server started running...");

    // [connect with Mongo DB here]
});

Open your terminal and you will see the message that the server has been started. You can access your project at http://localhost:3000/

Setup Mongo DB

Write the following lines in place of [include Mongo DB module here] section in your server.js file:

// include mongo DB
var mongodb = require("mongodb");
var MongoClient = mongodb.MongoClient;

Then connect the database in the [connect with Mongo DB here] section:

// connect with mongo DB server
MongoClient.connect("mongodb://localhost:27017", function (error, client) {
    if (error) {
        console.error(error);
        return;
    }

    // set database
    db = client.db("encrypt_decrypt_string");
    console.log("Database connected");

    // [routes goes here]

});

Save the file and open your terminal, now you will see another message that the database has been connected as well.

Encrypt the String

First, include the crypto module at the top of your server.js file:

// include crypto module
const crypto = require("crypto")

// set encryption algorithm
const algorithm = 'aes-256-cbc'

// private key
const key = "adnan-tech-programming-computers" // must be of 32 characters

// random 16 digit initialization vector
const iv = crypto.randomBytes(16)

The key and initialization vector can be any string of 32 and 16 characters respectively. But it is recommended to keep the key hard-coded and initialization vector to be random. Because IV will be saved in database.

We cannot save the key in the database, because if the database gets hacked then all your encrypted strings will be compromised as well.

After that, create a GET route that will encrypt the string and save in Mongo DB. Write the following code in the [routes goes here] section:

// route to encrypt the message
app.get("/encrypt/:message", async function (request, result) {
    // get message from URL
    const message = request.params.message;

	// random 16 digit initialization vector
	const iv = crypto.randomBytes(16);

    // encrypt the string using encryption algorithm, private key and initialization vector
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    let encryptedData = cipher.update(message, "utf-8", "hex");
    encryptedData += cipher.final("hex");

    // convert the initialization vector to base64 string
    const base64data = Buffer.from(iv, 'binary').toString('base64');
    
    // save encrypted string along wtih initialization vector in database
    await db.collection("strings").insertOne({
        iv: base64data,
        encryptedData: encryptedData
    });

    // show the encrypted message
    result.send(encryptedData);
});

Save the file and try to access the URL: http://localhost:3000/encrypt/This is a test string

You can write any string in the URL and you will see the encrypted text in the browser and also in your Mongo DB.

Show all Encrypted Strings

To show all encrypted strings, we are going to use a module named ejs. Write the following line at the top of your server.js file:

// set templating engine as EJS
app.set("view engine", "ejs");

The create the following GET route to show all encrypted strings:

// route to show all encrypted messages
app.get("/", async function (request, result) {
    // get all data from database
    const data = await db.collection("strings")
        .find({})
        .sort({
            _id: -1
        }).toArray();

    // render index.ejs
    result.render("index", {
        data: data
    });
});

Create a new folder named views and inside it create a file named index.ejs. It will have the following code:

<table>
    <% for (let d in data) { %>
        <tr>
            <td>
                <a href="/decrypt/<%= data[d].encryptedData %>" target="_blank">
                    <%= data[d].encryptedData %>
                </a>
            </td>
        </tr>
    <% } %>
</table>

Access the URL: http://localhost:3000/ and you will see all your encrypted strings in descending order.

Decrypt the String

To decrypt the string, create a GET route and fetch the encrypted string and initialization vector from Mongo DB. Then we can apply the decryption using key.

// route to decrypt the message
app.get("/decrypt/:encrypted", async function (request, result) {
    // get encrypted text from URL
    const encrypted = request.params.encrypted;

    // check if text exists in database
    const obj = await db.collection("strings").findOne({
        encryptedData: encrypted
    });

    if (obj == null) {
        result.status(404).send("Not found");
        return;
    }

    // convert initialize vector from base64 to buffer
    const origionalData = Buffer.from(obj.iv, 'base64') 

    // decrypt the string using encryption algorithm and private key
    const decipher = crypto.createDecipheriv(algorithm, key, origionalData);
    let decryptedData = decipher.update(obj.encryptedData, "hex", "utf-8");
    decryptedData += decipher.final("utf8");

    // display the decrypted string
    result.send(decryptedData);
});

If you click on any string now, you will see the actual string.

[wpdm_package id=’1554′]