You are on page 1of 50

WETEXT – A FULL STACK MERN CHAT APPLICATION

A Project (part of 8th Semester course Curriculum) submitted in Partial


fulfillment of the requirements for the degree of

BACHELOR OF TECHNOLOGY
in
COMPUTER SCIENCE AND ENGINEERING

By
SANDIP ADHIKARY (Roll no. - 34200119017)
SUBHOJIT SIKDAR (Roll no. - 34200119014)

Department of Computer Science and Engineering


FUTURE INSTITUTE of TECHNOLOGY
2023

DEPARTEMENT OF COMPUTER SCIENCE AND ENGINEERING

1|Page
FUTURE INSTITUTE OF TECHNOLOGY
KOLKATA – 7000154
2023

CERTIFICATE

This is to certify that the project work entitled “ WeText – A Full Stack MERN Chat Application “
and submitted by ………………Sandip Adhikary & Subhojit Sikdar…………………… towards the partial
fulfillment for the award of Bachelor of Technology in Computer Science and Engineering degree at
Future Institute of Technology, is carried out under the supervision of the department as part of 8 th
Semester course curriculum (Paper Name – PROJECT-III , Paper Code – PROJ CS881) and is a Bonafede
work done him/her (them).

The matter presented in the documentation has not been submitted for the award of any other degree
of this or any other Institute/University.

I wish them all the success in life.

Date : ……………………………………….
( Prof Abhijit Saha )
Head of the Department
Dept of Computer Sc. & Engg
Future Institute of Technology
Kolkata.

2|Page
ACKNOWLEDGEMENT

I/We, the student(s) of CSE 8th Semester, are submitting the Project work titled “…………… WeText – A Full
Stack MERN Chat Application………………… “ as part of 8th semester course curriculum which was carried
out by me/us under the guidance and supervision of the department of Computer Science and Engg and
express my/our sincere thanks to all the faculty and staff members of the department for their kind
cooperation.
I/ We would also like to thank our HOD for his guidance towards preparation and submission of the Project
work.

Thanking You,

Date : 17.05.2023
Place : Kolkata
1) Name : Sandip Adhikary

Signature:

Roll No. : 34200119017

2) Name : Subhojit Sikdar

Signature :

Roll No. : 34200119014

3|Page
SL.NO. Description Page No.

5
1 Abstract
6
2 Introduction
7
3 Objective
8
4 Scope
9
5 Feasibility Study
10-11
6 Work Flow
12
7 Components of the System
13
8 Input and Output
14
9 Hardware & Software Requirements
15-17
10 Diagram
18-21
11 Output Screen
22-46
12 Code
47
13 Future Scope and Further
Enhancements
48
14 Limitations
49
15 Conclusion
50
16 Bibliography

4|Page
1. ABSTRACT
In today's digital age, communication plays a crucial role in connecting
individuals across the globe. With the increasing demand for real-time
messaging applications, building a single message chat application has become
a popular endeavor. This abstract introduces a chat application developed using
the MERN (MongoDB, Express.js, React.js, and Node.js) technology stack,
highlighting its key features and functionality.
The proposed chat application leverages the MERN technology stack to provide
a robust and scalable solution. MongoDB, a NoSQL database, ensures efficient
data storage and retrieval, enabling seamless storage of user profiles and
message history. Express.js, a web application framework for Node.js,
facilitates the creation of a server-side backend that handles authentication,
routing, and interaction with the database. Node.js acts as the runtime
environment, executing JavaScript code on the server-side, enabling high-
performance communication. React.js, a JavaScript library, serves as the
frontend framework, providing an interactive and responsive user interface.
The chat application encompasses essential features such as user registration
and authentication, login & logout, and ability to send and receive messages in
real time.

5|Page
2. INTRODUCTION
Welcome to our Single Message Chat Application! With the power of
MERN technology, we've created a seamless platform for you to connect
and communicate with others in a simple and efficient way. Using the
MERN stack, which stands for MongoDB, Express.js, React.js, and Node.js,
we have built a robust and dynamic application that allows you to
exchange messages with ease. Let's take a closer look at each component:

MongoDB: Our application utilizes MongoDB, a popular NoSQL database,


to store and manage the chat messages. This ensures fast and efficient
retrieval of conversations, enabling real-time messaging.

Express.js: We leverage Express.js, a flexible and minimalistic web


application framework for Node.js, to handle server-side operations. It
simplifies the process of routing, handling requests, and managing
middleware, making the application more scalable and efficient.

React.js: The frontend of our chat application is built using React.js, a


powerful JavaScript library for building user interfaces. React.js allows us
to create a dynamic and responsive user experience, making real-time
messaging seamless and enjoyable.

Node.js: We rely on Node.js, a server-side JavaScript runtime


environment, to power the backend of our chat application. Node.js
enables event-driven, non-blocking I/O operations, resulting in a highly
scalable and efficient server architecture.

We're excited to have you on board and experience the convenience and
efficiency of our single message chat application. Start chatting and
connecting with us.

6|Page
3. OBJECTIVE
The objective of this project is to build a single message chat application
using the MERN (MongoDB, Express.js, React.js, Node.js) stack
technology. The application will allow users to send and receive messages
in real-time within a single conversation.

Key Features:
• User Registration and Authentication: Users will be able to create
accounts and log in to the application using their credentials. User
authentication will ensure secure access to the chat functionality.

• Real-time Messaging: Users will be able to send and receive


messages in real-time within a single conversation. The chat
interface should update instantly when a new message is sent or
received.

• Conversation History: The application should store and display the


chat history, allowing users to scroll through previous messages
within the conversation.

• Profile Picture: Uses will be able to pick an Avatar as their profile


picture and then set it as their profile picture.

• Deployment: Deploy the application to a web server or cloud


platform to make it accessible to users over the internet.

By achieving these objectives, you will create a single message chat


application using the MERN technology stack that provides users
with a seamless and real-time messaging experience.

7|Page
4. SCOPE
A single message chat application using the MERN (MongoDB, Express.js,
React.js, Node.js) technology stack can have various scopes and features. Here
are some possible scopes for a single message chat application:
• User Authentication: Implement a user authentication system to allow
users to create accounts, log in, and maintain their profiles.

• Real-Time Messaging: Enable real-time messaging capabilities using


technologies like Socket.io or Web-Sockets to ensure instant message
delivery and updates.

• User Name and Email Storage: Store name and email id of user in a
MongoDB database.

• Emoji’s and Reactions: Enable users to react to messages using emoji’s or


predefined reactions, enhancing the interactive experience.

• Cross-platform Compatibility: Ensure that the chat application works


seamlessly across multiple platforms, including web browsers, mobile
devices, and desktop applications.

• Message Encryption: Implement end-to-end encryption to ensure the


privacy and security of messages exchanged between users.

It's also essential to consider scalability, performance optimization, and


security measures when developing your chat application.

8|Page
5. FEASIBILITY STUDY
Feasibility study is made to see if the project on completion will serve the
purpose the organization for the amount of work.
Effort and the time that spend on it. Feasibility study lets the developer
foresee the future of the project and the usefulness. A Feasibility study of
a system proposal is according to its workability, which is the impact on
the organization, ability to meet their user needs and effective use of
resources. Thus when a new application is proposed it normally goes
through a feasibility study before it is approved for development.
The document provides the feasibility of the project that is being designed
and lists various area that were considered very carefully during the
feasibility study of this project such as Technical, Economic and
operational feasibilities.

The purpose of this feasibility study is to assess the viability and potential
success of developing a single message chat application using the MERN
(MongoDB, Express.js, React.js, Node.js) technology stack. The
application aims to provide users with a simple and efficient way to
exchange messages in real-time. The following factors will be considered
in this study:
Technical Feasibility:
a. Expertise: Evaluate the availability of developers with the necessary
skills and experience in MERN technology.
b. Infrastructure: Assess the required hardware and software
infrastructure for development, testing, and deployment of the
application.
c. Scalability: Determine if the MERN stack can handle the expected
number of users and message volume efficiently.
Market Feasibility:
a. Target Audience: Identify the potential user base and their specific
needs for a single message chat application.
b. Competition: Analyze the existing chat applications and their market
share to determine the potential for success and competitive advantage
of the proposed application.
9|Page
6. WORK FLOW
This Document plays a vital role in the development life cycle (SDLC) as it
describes the complete requirement of the system. It is meant for use by
the developers and will be the basic during testing phase. Any changes
made to the requirements in the future will have to go through formal
change approval process.

The Waterfall Model was first Process Model to be introduced. It is also


referred to as a linear-sequential life cycle model. It is very simple to
understand and use. In a waterfall model, each phase must be completed
before the next phase can begin and there is no overlapping in the phases.
Waterfall model is the earliest SDLC approach that was used for software
development.

The waterfall Model illustrates the software development process in a


linear sequential flow; hence it is also referred to as a linear-sequential
life cycle model. This means that any phase in the development process
begins only if the previous phase is complete. In waterfall model phases
do not overlap.

Waterfall Model design


Waterfall approach was first SDLC Model to be used widely in Software
Engineering to ensure success of the project. In "The Waterfall" approach,
the whole process of software development is divided into separate
phases. In Waterfall model, typically, the outcome of one phase acts as
the input for the next phase sequentially.
Following is a diagrammatic representation of different phases of
waterfall model.

10 | P a g e
The sequential phases in Waterfall model are:
• Requirement Gathering and analysis: All possible
requirements of the system to be developed are
captured in this phase and documented in a requirement
specification doc.
• System Design: The requirement specifications from
first phase are studied in this phase and system design is
prepared.
• Implementation: With inputs from system design, the
system is first developed in small programs called units,
which are integrated in the next phase.
• Integration and Testing: All the units developed in the
implementation phase are integrated into a system after
testing of each unit.

• Maintenance: There are some issues which come up in


the client environment. To fix those issues patches are
released.

11 | P a g e
7. COMPONENTS OF THE SYSTEM

The User Interface (UI) component presents the visual elements of the
chat application, including login/signup forms, chat interface, and user
list, ensuring an intuitive user experience.

The Authentication component handles user authentication and


authorization, allowing users to securely create accounts, log in, and
maintain session persistence.

The User Management component enables users to manage their


profiles, update personal information, and view other registered users
within the chat application.

The Chat Management component facilitates real-time message


exchanges, stores and retrieves messages from a database, and
dynamically updates the chat interface for seamless communication.

The Database component stores and manages user information,


messages, and chat history, ensuring data integrity and reliable data
retrieval.

The Real-time Communication component establishes a bidirectional


communication channel, enabling instant message delivery and real-time
updates between the server and clients.

The Emoji component enhances the chat experience by allowing users to


send and receive emojis, adding an element of fun and expression to their
conversations.

12 | P a g e
8. INPUT & OUTPUT

The main inputs, outputs and the major function in details are:

INPUT

• User can sign-in using email and password.

• User can login using the same email and password which they have
used in sign-in.

• User can visit the chat window and can chat to anyone who has an
account in the application.

• User can logout from the chat window.

OUTPUT

• User can see their other users in the application.

• User can view the messages.

• User can also interact with the other users and can send emojis.

13 | P a g e
9. HARDWARE AND SOFTWARE REQUIREMENTS

HARDWARE REQUIREMENTS:
• Computer that has a 1.6GHz or faster processor

• 1 GB (32 Bit) or 2 GB (64 Bit) RAM (Add 512


MB if running in a virtual machine)

• HDD 20 GB Hard Disk Space and Above


Hardware Requirements
• 5400 RPM hard disk drive

• DVD-ROM Drive

SOFTWARE REQUIREMENTS:

•WINDOWS OS (7/10/11)

•Visual Studio Code

•MongoDB Server

•Postman

•Node js

14 | P a g e
10.DIAGRAM

15 | P a g e
16 | P a g e
17 | P a g e
11.OUTPUT SCREEN

• User registration/create account page :

• User login page :

18 | P a g e
• Set profile picture page :

• Opening/home page :

19 | P a g e
• A Screenshot of the chat from Subhojit’s Perspective :

20 | P a g e
• A Screenshot of the chat from Dhoni’s Perspective :

21 | P a g e
12.CODE
• Frontend-

Login.jsx-

import React, { useState, useEffect } from "react";


import axios from "axios";
import styled from "styled-components";
import { useNavigate, Link } from "react-router-dom";
import Logo from "../assets/logo.png";
import Video from "../assets/video.mp4";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { loginRoute } from "../utils/APIRoutes";

export default function Login() {


const navigate = useNavigate();
const [values, setValues] = useState({ username: "", password: "" });
const toastOptions = {
position: "bottom-right",
autoClose: 8000,
pauseOnHover: true,
draggable: true,
theme: "dark",
};
useEffect(() => {
if (localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/");
}
}, []);

const handleChange = (event) => {


setValues({ ...values, [event.target.name]: event.target.value });
};

22 | P a g e
const validateForm = () => {
const { username, password } = values;
if (username === "") {
toast.error("Email and Password is required.", toastOptions);
return false;
} else if (password === "") {
toast.error("Email and Password is required.", toastOptions);
return false;
}
return true;
};

const handleSubmit = async (event) => {


event.preventDefault();
if (validateForm()) {
const { username, password } = values;
const { data } = await axios.post(loginRoute, {
username,
password,
});
if (data.status === false) {
toast.error(data.msg, toastOptions);
}
if (data.status === true) {
localStorage.setItem(
process.env.REACT_APP_LOCALHOST_KEY,
JSON.stringify(data.user)
);

navigate("/");
}
}
};

return (

23 | P a g e
<>
<video autoPlay muted loop id="Video">
<source src={ Video} type="video/mp4" />
</video>
<FormContainer>
<form action="" onSubmit={(event) => handleSubmit(event)}>
<div className="brand">
<img src={Logo} alt="logo" />
<h1>We-Text</h1>
</div>
<input
type="text"
placeholder="Username"
name="username"
onChange={(e) => handleChange(e)}
min="3"
/>
<input
type="password"
placeholder="Password"
name="password"
onChange={(e) => handleChange(e)}
/>
<button type="submit">Log In</button>
<span>
NEW HERE ? <Link to="/register">Create Your Account</Link>
</span>
<div className="socialmedia">
<span> Contact Me</span>
</div>
</form>
</FormContainer>
<ToastContainer />
</>
);
}

24 | P a g e
Register.jsx-

import React, { useState, useEffect } from "react";


import axios from "axios";
import styled from "styled-components";
import { useNavigate, Link } from "react-router-dom";
import Logo from "../assets/logo.png";
import Video from "../assets/video.mp4";

import { ToastContainer, toast } from "react-toastify";


import "react-toastify/dist/ReactToastify.css";
import { registerRoute } from "../utils/APIRoutes";

export default function Register() {


const navigate = useNavigate();
const toastOptions = {
position: "bottom-right",
autoClose: 8000,
pauseOnHover: true,
draggable: true,
theme: "dark",
};
const [values, setValues] = useState({
username: "",
email: "",
password: "",
confirmPassword: "",
});

useEffect(() => {
if (localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/");
}
}, []);

const handleChange = (event) => {

25 | P a g e
setValues({ ...values, [event.target.name]: event.target.value });
};

const handleValidation = () => {


const { password, confirmPassword, username, email } = values;
if (password !== confirmPassword) {
toast.error(
"Password and confirm password should be same.",
toastOptions
);
return false;
} else if (username.length < 3) {
toast.error(
"Username should be greater than 3 characters.",
toastOptions
);
return false;
} else if (password.length < 8) {
toast.error(
"Password should be equal or greater than 8 characters.",
toastOptions
);
return false;
} else if (email === "") {
toast.error("Email is required.", toastOptions);
return false;
}

return true;
};

const handleSubmit = async (event) => {


event.preventDefault();
if (handleValidation()) {
const { email, username, password } = values;
const { data } = await axios.post(registerRoute, {

26 | P a g e
username,
email,
password,
});

if (data.status === false) {


toast.error(data.msg, toastOptions);
}
if (data.status === true) {
localStorage.setItem(
process.env.REACT_APP_LOCALHOST_KEY,
JSON.stringify(data.user)
);
navigate("/");
}
}
};

return (
<>
<video autoPlay muted loop id="Video">
<source src={ Video} type="video/mp4" />
</video>

<FormContainer>

<form action="" onSubmit={(event) => handleSubmit(event)}>


<div className="brand">
<img src={Logo} alt="logo" />
<h1>We-Text</h1>
</div>
<input
type="text"
placeholder="Username"
name="username"

27 | P a g e
onChange={(e) => handleChange(e)}
/>
<input
type="email"
placeholder="Email"
name="email"
onChange={(e) => handleChange(e)}
/>
<input
type="password"
placeholder="Password"
name="password"
onChange={(e) => handleChange(e)}
/>
<input
type="password"
placeholder="Confirm Password"
name="confirmPassword"
onChange={(e) => handleChange(e)}
/>
<button type="submit">Create Account</button>
<span>
HAVE AN EXISTING ACCOUNT ? <Link to="/login">Login.</Link>
</span>
</form>
</FormContainer>
<ToastContainer />
</>
);
}

28 | P a g e
Chat.jsx-

import React, { useEffect, useState, useRef } from "react";


import axios from "axios";
import { useNavigate } from "react-router-dom";
import { io } from "socket.io-client";
import styled from "styled-components";
import { allUsersRoute, host } from "../utils/APIRoutes";
import ChatContainer from "../components/ChatContainer";
import Contacts from "../components/Contacts";
import Welcome from "../components/Welcome";
import Video from "../assets/video.mp4";

export default function Chat() {


const navigate = useNavigate();
const socket = useRef();
const [contacts, setContacts] = useState([]);
const [currentChat, setCurrentChat] = useState(undefined);
const [currentUser, setCurrentUser] = useState(undefined);
useEffect(async () => {
if (!localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/login");
} else {
setCurrentUser(
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)
);
}
}, []);
useEffect(() => {
if (currentUser) {
socket.current = io(host);
socket.current.emit("add-user", currentUser._id);
}
}, [currentUser]);

29 | P a g e
useEffect(async () => {
if (currentUser) {
if (currentUser.isAvatarImageSet) {
const data = await axios.get(`${allUsersRoute}/${currentUser._id}`);
setContacts(data.data);
} else {
navigate("/setAvatar");
}
}
}, [currentUser]);
const handleChatChange = (chat) => {
setCurrentChat(chat);
};
return (
<>
<Container>
<div className="container">
<Contacts contacts={contacts} changeChat={handleChatChange} />
{currentChat === undefined ? (
<Welcome />
):(
<ChatContainer currentChat={currentChat} socket={socket} />
)}
</div>
</Container>
</>
);
}

30 | P a g e
Contacts.jsx -

import React, { useState, useEffect } from "react";


import styled from "styled-components";
import Logo from "../assets/logo.png";

export default function Contacts({ contacts, changeChat }) {


const [currentUserName, setCurrentUserName] = useState(undefined);
const [currentUserImage, setCurrentUserImage] = useState(undefined);
const [currentSelected, setCurrentSelected] = useState(undefined);
useEffect(async () => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
setCurrentUserName(data.username);
setCurrentUserImage(data.avatarImage);
}, []);
const changeCurrentChat = (index, contact) => {
setCurrentSelected(index);
changeChat(contact);
};
return (
<>
{currentUserImage && currentUserImage && (
<Container>
<div className="brand">
<img src={Logo} alt="logo" />
<h3>We-Text</h3>
</div>
<div className="contacts">
{contacts.map((contact, index) => {
return (
<div
key={contact._id}
className={`contact ${
index === currentSelected ? "selected" : ""
31 | P a g e
}`}
onClick={() => changeCurrentChat(index, contact)}
>
<div className="avatar">
<img
src={`data:image/svg+xml;base64,${contact.avatarImage}`}
alt=""
/>
</div>
<div className="username">
<h3>{contact.username}</h3>
</div>
</div>
);
})}
</div>
<div className="current-user">
<div className="avatar">
<img
src={`data:image/svg+xml;base64,${currentUserImage}`}
alt="avatar"
/>
</div>
<div className="username">
<h2>{currentUserName}</h2>
</div>
</div>
</Container>
)}
</>
);
}

32 | P a g e
ChatInput.jsx-

import React, { useState } from "react";


import { BsEmojiSmileFill } from "react-icons/bs";
import { IoMdSend } from "react-icons/io";
import styled from "styled-components";
import Picker from "emoji-picker-react";

export default function ChatInput({ handleSendMsg }) {


const [msg, setMsg] = useState("");
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const handleEmojiPickerhideShow = () => {
setShowEmojiPicker(!showEmojiPicker);
};
const handleEmojiClick = (event, emojiObject) => {
let message = msg;
message += emojiObject.emoji;
setMsg(message);
};
const sendChat = (event) => {
event.preventDefault();
if (msg.length > 0) {
handleSendMsg(msg);
setMsg("");

33 | P a g e
}
};
return (
<Container>
<div className="button-container">
<div className="emoji">
<BsEmojiSmileFill onClick={handleEmojiPickerhideShow} />
{showEmojiPicker && <Picker onEmojiClick={handleEmojiClick} />}
</div>
</div>
<form className="input-container" onSubmit={(event) =>
sendChat(event)}>
<input
type="text"
placeholder="Type your message here"
onChange={(e) => setMsg(e.target.value)}
value={msg}
/>
<button type="submit">
<IoMdSend />
</button>
</form>
</Container>
);
}
34 | P a g e
Logout.jsx-
import React from "react";
import { useNavigate } from "react-router-dom";
import { BiPowerOff } from "react-icons/bi";
import styled from "styled-components";
import axios from "axios";
import { logoutRoute } from "../utils/APIRoutes";
export default function Logout() {
const navigate = useNavigate();
const handleClick = async () => {
const id = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)._id;
const data = await axios.get(`${logoutRoute}/${id}`);
if (data.status === 200) {
localStorage.clear();
navigate("/login");
}
};
return (
<Button onClick={handleClick}>
<BiPowerOff />
<h3> Logout</h3>
</Button>

35 | P a g e
);
}

ChatContainer.jsx-

import React, { useState, useEffect, useRef } from "react";


import styled from "styled-components";
import ChatInput from "./ChatInput";
import Logout from "./Logout";
import { v4 as uuidv4 } from "uuid";
import axios from "axios";
import { sendMessageRoute, recieveMessageRoute } from
"../utils/APIRoutes";

export default function ChatContainer({ currentChat, socket }) {


const [messages, setMessages] = useState([]);
const scrollRef = useRef();
const [arrivalMessage, setArrivalMessage] = useState(null);

useEffect(async () => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
const response = await axios.post(recieveMessageRoute, {
from: data._id,
36 | P a g e
to: currentChat._id,
});
setMessages(response.data);
}, [currentChat]);

useEffect(() => {
const getCurrentChat = async () => {
if (currentChat) {
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)._id;
}
};
getCurrentChat();
}, [currentChat]);

const handleSendMsg = async (msg) => {


const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
socket.current.emit("send-msg", {
to: currentChat._id,
from: data._id,
msg,

37 | P a g e
});
await axios.post(sendMessageRoute, {
from: data._id,
to: currentChat._id,
message: msg,
});

const msgs = [...messages];


msgs.push({ fromSelf: true, message: msg });
setMessages(msgs);
};

useEffect(() => {
if (socket.current) {
socket.current.on("msg-recieve", (msg) => {
setArrivalMessage({ fromSelf: false, message: msg });
});
}
}, []);

useEffect(() => {
arrivalMessage && setMessages((prev) => [...prev, arrivalMessage]);
}, [arrivalMessage]);

38 | P a g e
useEffect(() => {
scrollRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);

return (
<Container>
<div className="chat-header">
<div className="user-details">
<div className="avatar">
<img
src={`data:image/svg+xml;base64,${currentChat.avatarImage}`}
alt=""
/>
</div>
<div className="username">
<h3>{currentChat.username}</h3>
</div>
</div>
<Logout />
</div>
<div className="chat-messages">
{messages.map((message) => {
return (
<div ref={scrollRef} key={uuidv4()}>

39 | P a g e
<div
className={`message ${
message.fromSelf ? "sended" : "recieved"
}`}
>
<div className="content ">
<p>{message.message}</p>
</div>
</div>
</div>
);
})}
</div>
<ChatInput handleSendMsg={handleSendMsg} />
</Container>
);
}

40 | P a g e
Welcome.jsx-

import React, { useState, useEffect } from "react";


import styled from "styled-components";
import Robot from "../assets/robot.gif";
export default function Welcome() {
const [userName, setUserName] = useState("");
useEffect(async () => {
setUserName(
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
).username
);
}, []);
return (
<Container>
<img src={Robot} alt="" />
<h1>
Welcome, <span>{userName}!</span>
</h1>
<h3>Please select a chat to Start messaging.</h3>
</Container>
);
}

41 | P a g e
index.js-

import React from "react";


import ReactDOM from "react-dom";
import App from "./App";
import "./index.css";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);

App.js-

import React, { Suspense, lazy } from "react";


import { BrowserRouter, Routes, Route } from "react-router-dom";

const Chat = lazy(() => import("./pages/Chat"));


const Login = lazy(() => import("./pages/Login"));
const Register = lazy(() => import("./pages/Register"));
const SetAvatar = lazy(() => import("./components/SetAvatar"));

42 | P a g e
export default function App() {
return (
<BrowserRouter>
<Suspense fallback={<></>}>
<Routes>
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route path="/setAvatar" element={<SetAvatar />} />
<Route path="/" element={<Chat />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}

APIRoutes.js-
export const host = "https://we-text.onrender.com";
export const loginRoute = `${host}/api/auth/login`;
export const registerRoute = `${host}/api/auth/register`;
export const logoutRoute = `${host}/api/auth/logout`;
export const allUsersRoute = `${host}/api/auth/allusers`;
export const sendMessageRoute = `${host}/api/messages/addmsg`;
export const recieveMessageRoute = `${host}/api/messages/getmsg`;
export const setAvatarRoute = `${host}/api/auth/setavatar`;

43 | P a g e
• Backend-
messages.js-
const { addMessage, getMessages } =
require("../controllers/messageController");
const router = require("express").Router();
router.post("/addmsg/", addMessage);
router.post("/getmsg/", getMessages);
module.exports = router;

auth.js-
const {
login,
register,
getAllUsers,
setAvatar,
logOut,
} = require("../controllers/userController");
const router = require("express").Router();
router.post("/login", login);
router.post("/register", register);
router.get("/allusers/:id", getAllUsers);
router.post("/setavatar/:id", setAvatar);
router.get("/logout/:id", logOut);
module.exports = router;
44 | P a g e
index.js-
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const authRoutes = require("./routes/auth");
const messageRoutes = require("./routes/messages");
const app = express();
const socket = require("socket.io");
require("dotenv").config();
app.use(cors());
app.use(express.json());
mongoose
.connect(process.env.MONGO_URL, useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("DB Connection Successful");
})
.catch((err) => {
console.log(err.message);
});
app.use("/api/auth", authRoutes);
app.use("/api/messages", messageRoutes);
const server = app.listen(process.env.PORT, () =>

45 | P a g e
console.log(`Server started on ${process.env.PORT}`) );
const io = socket(server, {
cors: {
origin: ["http://localhost:3000", "https://we-text.onrender.com/"],
credentials: true,
},
});
global.onlineUsers = new Map();
io.on("connection", (socket) => {
global.chatSocket = socket;
socket.on("add-user", (userId) => {
onlineUsers.set(userId, socket.id);
});
socket.on("send-msg", (data) => {
const sendUserSocket = onlineUsers.get(data.to);
if (sendUserSocket) {
socket.to(sendUserSocket).emit("msg-recieve", data.msg);
}
});
});
app.use(express.static(path.join(__dirname, "./public/build")));
app.get("*", function (req, res) {
res.sendFile(path.join(__dirname, "./public/build/index.html"));
});

46 | P a g e
13.FUTURE SCOPE AND FURTHER ENHANCEMENTS

A single message chat application built using the MERN (MongoDB,


Express.js, React.js, Node.js) technology stack can be further enhanced
and expanded in several ways to improve its functionality and user
experience. Here are some future scope and further enhancements for
your single message chat application:

Real-time Messaging: Implement real-time messaging using technologies


like Web-Sockets or a library like Socket.IO. This will allow users to see
messages instantly without needing to refresh the page.

User Authentication and Authorization: Enhance the application by


implementing user authentication and authorization mechanisms. This
will enable users to create accounts, log in, and have personalized chat
experiences.

Emoji’s and Reactions: Enable users to express their emotions and


reactions using emoji’s or predefined reactions. Implement a reaction
system similar to social media platforms where users can add emoji’s or
"like" messages.

Mobile Application: Consider developing a mobile application version of


the chat application for both iOS and Android platforms. This can broaden
the user base and provide a seamless mobile chat experience.

47 | P a g e
14.LIMITATIONS

There are several limitations that you may encounter when developing a
single message chat application using the MERN (MongoDB, Express.js,
React, Node.js) technology stack. Here are a few potential limitations:

Scalability: The MERN stack can handle moderate levels of traffic and
users, but it may face scalability challenges when dealing with a large
number of concurrent connections or heavy message traffic. Scaling the
application to handle high loads might require implementing techniques
such as load balancing, horizontal scaling, or using a dedicated messaging
service.

Performance: As the number of messages increases, fetching and


rendering all the messages on the client side could lead to performance
issues. It's important to implement pagination or infinite scrolling to limit
the number of messages loaded at a time and optimize the rendering
process.

Security: Security is a critical aspect of any chat application. MERN


provides tools and libraries for handling security concerns, such as
authentication and authorization, but it's essential to ensure that proper
security measures are implemented to protect user data, prevent
unauthorized access, and secure communication channels.

Offline functionality: MERN does not natively support offline


functionality. If users need to access the chat application or send
messages while offline, you would need to implement additional
techniques such as client-side caching or using a service worker to handle
offline data synchronization.

Mobile app development: While MERN is well-suited for web


applications, if we plan to develop a mobile app version, additional
frameworks or technologies, such as React Native or Flutter, would be
required. This introduces the need for separate codebases and additional
development efforts.
48 | P a g e
15.CONCLUSION

In conclusion, building a single message chat application using the MERN


(MongoDB, Express.js, React.js, Node.js) technology stack provides
several benefits and advantages.

The MERN stack offers a comprehensive solution for developing a chat


application that supports real-time communication. By leveraging web-
sockets or similar technologies, users can instantly exchange messages.

The MERN stack supports the creation of cross-platform applications,


allowing users to access the chat application from various devices and
operating systems.

Using JavaScript throughout the entire stack provides a developer-


friendly environment. It reduces the learning curve, promotes code
consistency, and facilitates easier code maintenance.

The MERN stack benefits from a large and active community. This means
developers can find extensive resources, tutorials, and libraries to assist
in the development process and troubleshoot any issues.

While considering the advantages of the MERN stack, it's crucial to take
into account the specific requirements and constraints of your project.
Proper planning, architectural considerations, and adherence to best
practices are essential for ensuring a secure, efficient, and user-friendly
single message chat application.

MERN stack provides a unified and consistent development experience


since JavaScript is used throughout the entire stack. This reduces the
learning curve for developers and allows for easier code maintenance.

49 | P a g e
16.BIBLIOGRAPHY

• React Documentation- Retrieved from https://react.dev/learn

• Node.js Documentation- Retrieved from


https://nodejs.org/en/docs

• Express Documentation- Retrieved from


https://expressjs.com/en/4x/api.html

• MongoDB Documentation- Retrieved from


https://docs.mongodb.com/manual

• Socket.io Documentation- Retrieved from


https://socket.io/docs/v4

• W3Schools- Retrieved from https://www.w3schools.com

• Emoji Mart- Retrieved from


https://www.npmjs.com/package/emoji-mart

-Thank You

------------X-----------

50 | P a g e

You might also like