Webx Technology

Build a Full-Stack App with React, Node.js & MongoDB

October 20, 2026 by Guru Ji | Filed under Uncategorized.

How to Build a Full-Stack Web App with React, Node.js, and MongoDB

A simple MERN stack tutorial for freshers: Build a task manager app step by step.

Key Takeaways

  •     A full-stack web app has three parts: a front end (what users see), a back end (the logic), and a database (the saved data).
  •     In the MERN stack, MongoDB stores the data, Express and Node.js run the back end, and React builds the front end.
  •     In this MERN stack tutorial for beginners, you will build a task manager with a REST API and a React screen.
  •     Build and test the back end first. Then build the front end. This makes errors much easier to find.
  •     Type the code yourself instead of only copying it. You will learn much more, and you can explain it in an interview.

What Is a Full Stack Web App?

Think of a restaurant. The dining area is the front end, where customers sit and order. The kitchen is the back end, where the food is made. The storeroom is the database, where all the ingredients are kept. A full stack developer can work on all three parts.

 

Every time you log in to a website, post a comment or save an item to a cart, you are using a full stack web app. That is why a full-stack project for freshers is one of the best things you can add to your resume.

What Is the MERN Stack?

MERN stands for MongoDB, Express.js, React and Node.js. All four tools use JavaScript, so you only need to learn one language for the whole app. This is why many freshers start with MERN.

 

Here is how it works. When a user clicks a button, React sends a request to the Express server. The server asks MongoDB for the data and sends the answer back as JSON. React then shows it on the screen.

What Are We Going to Build?

We will build a small task manager. A user can see a list of tasks, add a new task and delete a task. It looks simple, but it teaches the most important idea in web development: CRUD.

 

  •     Create: add a new task
  •     Read: show all tasks
  •     Update: mark a task as done
  •     Delete: remove a task

What You Need Before You Start

  •     Node.js installed on your computer (the LTS version is the safest choice)
  •     A code editor such as VS Code
  •     A free MongoDB Atlas account (a cloud database), or MongoDB installed on your computer
  •     Basic knowledge of HTML, CSS and JavaScript
  •     Postman or the Thunder Client extension to test your API
  •     Git installed and a free GitHub account

Project Roadmap at a Glance

Here are the seven steps we will follow. Step 7 is a bonus for students who want to go further.

Step 1: Set Up the Project Folders

Create one main folder. Inside it, we will keep the back end in a folder called server and the front end in a folder called client. Keeping them separate keeps your code clean.

 

mkdir task-manager

cd task-manager

mkdir server

 

The client folder will be created for us in Step 5. At the end, your project will look like this:

 

task-manager/

  server/

models/Task.js

routes/tasks.js

server.js

.env

  client/

Step 2: Build the Back End with Node.js and Express

Open the server folder in your terminal. Create a package.json file and install the packages we need.

 

cd server

npm init -y

npm install express mongoose cors dotenv

 

  •     express makes it easy to create a server and routes.
  •     mongoose helps Node.js talk to MongoDB.
  •     cors lets your React app call your API.
  •     dotenv reads secret values from a .env file.

 

Now create a file called server.js and add this code:

 

require(“dotenv”).config();

const express = require(“express”);

const cors = require(“cors”);

const mongoose = require(“mongoose”);

 

const app = express();

app.use(cors());

app.use(express.json());

 

app.use(“/api/tasks”,

  require(“./routes/tasks”));

 

mongoose

  .connect(process.env.MONGO_URI)

  .then(() => {

app.listen(5000, () =>

   console.log(“Server is running”));

  })

  .catch((err) => console.log(err));

 

Let us understand the important lines. express.json() lets the server read JSON data sent from React. cors() allows your front end to call the server. The server starts only after the database connection is successful.

Step 3: Connect MongoDB and Create a Model

Log in to MongoDB Atlas and create a free cluster. Then create a database user, add your IP address in Network Access, and copy your connection string. Save it in a file called .env inside the server folder:

 

MONGO_URI=paste_your_connection_string

Important: Never upload your .env file to GitHub. Create a .gitignore file and add .env to it.

 

A model tells MongoDB what a task looks like. Create the file models/Task.js:

 

const mongoose = require(“mongoose”);

 

const taskSchema = new mongoose.Schema({

  title: {

type: String,

required: true,

  },

  done: {

type: Boolean,

default: false,

  },

});

 

module.exports =

  mongoose.model(“Task”, taskSchema);

 

Each task has a title (text) and a done value (true or false). New tasks start with done as false.

Step 4: Create the REST API (CRUD)

A REST API is a set of URLs that the front end can call to ask the back end to do something. Our task manager needs four of them:

 

Action

Method

URL

Create

POST

/api/tasks

Read

GET

/api/tasks

Update

PUT

/api/tasks/:id

Delete

DELETE

/api/tasks/:id

 

Create the file routes/tasks.js. Start with these three lines:

const express = require(“express”);

const Task = require(“../models/Task”);

const router = express.Router();

Read all tasks:

router.get(“/”, async (req, res) => {

  const tasks = await Task.find();

  res.json(tasks);

});

 

Create a new task:

router.post(“/”, async (req, res) => {

  const task = await Task.create({

title: req.body.title,

  });

  res.status(201).json(task);

});

Update a task (mark it as done):

router.put(“/:id”, async (req, res) => {

  const task = await Task.findById(

req.params.id

  );

  task.done = req.body.done;

  await task.save();

  res.json(task);

});

 

Delete a task, and then export the router:

router.delete(“/:id”,

  async (req, res) => {

await Task.findByIdAndDelete(

   req.params.id

);

res.json({ message: “Deleted” });

  });

 

module.exports = router;

Now start the server from the server folder:

node server.js

 

You should see “Server is running” in the terminal. Open http://localhost:5000/api/tasks in your browser. You will see an empty list []. Next, use Postman or Thunder Client to send a POST request to the same URL with this body:

{ “title”: “Learn React” }

 

Open the GET URL again. Your task should now appear. Your back end is working.

 

Note: In a real project, you should wrap each route in try/catch to handle errors. We keep the code short here so it is easy to read.

 

Step 5: Build the Front End with React

Open a new terminal in the main task-manager folder and create a React app with Vite. When Vite asks questions, choose React and then JavaScript.

 

cd ..

npm create vite@latest client

 

Then install the packages and start the app:

cd client

npm install

npm run dev

 

Open the file src/App.jsx, delete everything inside it and write the code below. We will build it in small parts. First, the imports and the address of our back end:

 

import { useState } from “react”;

import { useEffect } from “react”;

 

const API =

  “http://localhost:5000/api/tasks”;

 

Next, create the component. We use state to remember the list of tasks and the text typed in the input box:

 

function App() {

  const [tasks, setTasks] = useState([]);

  const [title, setTitle] = useState(“”);

 

Now load the tasks when the page opens. The empty [] at the end means this code runs only once:

 

  useEffect(() => {

fetch(API)

   .then((res) => res.json())

   .then((data) => setTasks(data));

  }, []);

 

Add a function that sends a new task to the back end and then adds it to the list on screen:

 

  const addTask = async () => {

const res = await fetch(API, {

   method: “POST”,

   headers: {

     “Content-Type”: “application/json”,

   },

   body: JSON.stringify({ title }),

});

const newTask = await res.json();

setTasks([…tasks, newTask]);

setTitle(“”);

  };

Add a function to delete a task:

  const deleteTask = async (id) => {

await fetch(API + “/” + id, {

   method: “DELETE”,

});

const left = tasks.filter(

   (t) => t._id !== id

);

setTasks(left);

  };

 

Finally, write what the user will see on the screen. This is called JSX:

 

  return (

<div>

   <h1>My Tasks</h1>

   <input

     value={title}

     placeholder=”Add a task”

     onChange={(e) =>

       setTitle(e.target.value)

     }

   />

   <button onClick={addTask}>

     Add

   </button>

   <ul>

     {tasks.map((t) => (

       <li key={t._id}>

         {t.title}

         <button

           onClick={() =>

            deleteTask(t._id)

           }

         >

           Delete

         </button>

       </li>

     ))}

   </ul>

</div>

  );

}

 

export default App;

 

Practice task: Add a button that marks a task as done. Use the PUT route we already built.

 

Step 6: Connect the Front End and Back End

 

Both parts must run at the same time, so keep two terminals open.

  •     Terminal 1 (inside server): run node server.js
  •     Terminal 2 (inside client): run npm run dev

 

Open the address shown by Vite, usually

http://localhost:5173. Add a task and refresh the page. The task is still there because it is saved in MongoDB. That means your full stack app is working.

 

If you see a CORS error in the browser, check that app.use(cors()) is in server.js and restart the server.

 

Tip for later: When you deploy, do not keep the API address inside your code. In Vite, you can save it in a .env file as VITE_API_URL and read it with import.meta.env.VITE_API_URL.

 

Step 7 (Bonus): Add Login with JWT

Right now, anyone can use your API. JWT (JSON Web Token) is a popular way to check who a user is. Here is how it works:

 

  1.   The user registers. The server saves the user and hashes the password with bcryptjs. Never save plain passwords.
  2.   The user logs in. The server checks the password and creates a token with jsonwebtoken.
  3.   React saves the token and sends it with every request in the Authorization header.
  4.   The server checks the token before it allows access to protected routes.

 

Install the packages in the server folder:

 

npm install bcryptjs jsonwebtoken

 

Add a long random value called JWT_SECRET to your .env file. Then create a middleware file that checks the token:

 

const jwt = require(“jsonwebtoken”);

 

module.exports = (req, res, next) => {

  const auth = req.headers.authorization;

  const token = auth && auth.split(” “)[1];

  try {

jwt.verify(

   token,

   process.env.JWT_SECRET

);

next();

  } catch (err) {

res.status(401).json({

   message: “Please log in”,

});

  }

};

 

You also need register and login routes. The login route creates the token with jwt.sign. Then you can add this middleware to any route you want to protect.

 

Where should React keep the token? Many learners use localStorage while practising. For real apps, secure cookies are the safer choice.

 

Common Errors and Easy Fixes

Every developer sees errors. Use this table when something goes wrong.

Error

Why it happens

Easy fix

CORS error

Server does not allow the front end

Add cors() and restart the server

Cannot GET /api/tasks

Wrong URL or route not connected

Check the route path in server.js

MongoDB connection failed

Wrong password or IP not allowed

Check .env and add your IP in Atlas

undefined in process.env

The .env file was not loaded

Call dotenv at the top of server.js

Port already in use

Another app uses the same port

Stop the old server or change the port

Module not found

Package is not installed

Run npm install in that folder

 

Common Mistakes to Avoid

  •     Copying code without understanding it. Change small things and see what happens.
  •     Building the front end before testing the API.
  •     Uploading the .env file or passwords to GitHub.
  •     Saving plain text passwords in the database.
  •     Not using Git from the first day.
  •     Giving up when you see a red error. Read the message carefully. It usually tells you the file and the line.

What to Learn Next

  •     Add more features: edit a task, search tasks and a login screen.
  •     Style your app with CSS, Bootstrap or Tailwind CSS.
  •     Learn basic testing for your API and your React components.
  •     Deploy your app so that anyone can open it with a link.
  •     Put the project on GitHub with a clear README and screenshots.
  •     Prepare for interviews with our guide on full stack developer interview questions and answers.

Frequently Asked Questions

Yes. It uses JavaScript in every layer, so you learn one language for the whole app. Always check job descriptions in your city to see which tools companies ask for.

 No. Start with plain React and JavaScript. You can add them later.

 Both are fine. MongoDB is easy to start with in MERN because data looks like JavaScript objects. It is also a good idea to learn SQL, because many companies use it.

It depends on your background and how much you practise each day. Most learners need several months of regular practice. It is a path, not a promise of a fixed number of weeks.

Yes, but make it your own. Add features such as login, search and categories. Upload it to GitHub and be ready to explain every part in an interview.

Learn Full Stack Development in Mohali

Building projects is the best way to learn, and a good mentor makes it faster. If you are looking for full stack development training in Mohali, WebX Technology can help you learn with hands-on practice and project work. Visit webxtechnology.org to see the course details and pick a duration that suits you.

← Previous

Get Started

Address

SCO: 126-127, Sector 34A, Chandigarh.
Call Us: (0172)-4788480
Mobile: +91-9872755449
E-mail: webx34a@gmail.com

Plot No. C-133, Ind. Area Phase-8 Sector 72 Mohali
Call Us: (0172)-5078480
Mobile: +91-9872755449
E-mail: webx34a@gmail.com