Step-by-Step Tutorial: Building a MERN Stack Application from Scratch

Sriram s
5 min readNov 26, 2023

Introduction:

Embarking on the journey of building a full-stack application using the MERN stack can be both exciting and rewarding. In this step-by-step tutorial, we will guide you through the process of creating a MERN stack application from scratch. Whether you’re a beginner or looking to enhance your skills, this tutorial provides a hands-on approach to understanding each component of the MERN stack and how they seamlessly integrate to bring your web application to life.

Prerequisites:

Before we dive in, make sure you have the following installed on your machine:

  • Node.js and npm
  • MongoDB
  • Code editor (e.g., Visual Studio Code)
  • Git (optional but recommended)

Step 1: Setting Up Your Project

Start by creating a new directory for your project. Open a terminal and navigate to the project folder. Run the following commands:

mkdir mern-stack-app
cd mern-stack-app

Step 2: Backend Development with Node.js and Express

2.1 Initialize Node.js Server

Create a package.json file for your Node.js server:

npm init -y

2.2 Install Dependencies

Install Express and other necessary packages:

npm install express mongoose cors

2.3 Create Your Express Server

Create a file named server.js and set up your Express server:

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
const PORT = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
// Connect to MongoDB
mongoose.connect('mongodb://localhost/mern-stack-db', { useNewUrlParser: true, useUnifiedTopology: true });
// Define routes and middlewareapp.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

Step 3: MongoDB Database Setup

3.1 Install MongoDB

Install MongoDB on your machine. Follow the instructions on the official MongoDB website for your operating system.

3.2 Create a Database and Define a Model

In your server.js file, define a basic MongoDB model for your application:

const todoSchema = new mongoose.Schema({
task: String,
completed: Boolean,
});
const Todo = mongoose.model('Todo', todoSchema);

Step 4: Frontend Development with React

4.1 Initialize React App

In the root folder of your project, run:

npx create-react-app client

4.2 Install Axios for API Requests

cd client
npm install axios

4.3 Create a Simple Component

Replace the contents of src/App.js with a basic React component:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
const App = () => {
const [todos, setTodos] = useState([]);
useEffect(() => {
// Fetch data from the Express server
axios.get('http://localhost:5000/todos')
.then(response => setTodos(response.data))
.catch(error => console.error(error));
}, []);
return (
<div>
<h1>MERN Stack Todo App</h1>
<ul>
{todos.map(todo => (
<li key={todo._id}>{todo.task}</li>
))}
</ul>
</div>
);
};
export default App;

Step 5: Connecting Frontend to Backend

In your server.js file, create a route to fetch todos:

// Add this to server.js
app.get('/todos', async (req, res) => {
const todos = await Todo.find();
res.json(todos);
});

Update the React component to fetch and display data:

// Update App.js
// ... (existing code)
useEffect(() => {
axios.get('http://localhost:5000/todos')
.then(response => setTodos(response.data))
.catch(error => console.error(error));
}, []);
// ... (existing code)

Step 6: Creating Components and Implementing CRUD Operations

6.1 Create a Todo Form Component

Create a new file in the client/src directory named TodoForm.js:

import React, { useState } from 'react';
import axios from 'axios';
const TodoForm = ({ onAdd }) => {
const [task, setTask] = useState('');
const addTodo = async () => {
try {
const response = await axios.post('http://localhost:5000/todos', { task });
onAdd(response.data);
setTask('');
} catch (error) {
console.error(error);
}
};
return (
<div>
<input type="text" value={task} onChange={(e) => setTask(e.target.value)} />
<button onClick={addTodo}>Add Todo</button>
</div>
);
};
export default TodoForm;

6.2 Update App.js to Include TodoForm

//App.js
// ... (existing code)
import TodoForm from './TodoForm';const App = () => {
// ... (existing code)
const addTodo = (newTodo) => {
setTodos([...todos, newTodo]);
};
return (
<div>
<h1>MERN Stack Todo App</h1>
<TodoForm onAdd={addTodo} />
<ul>
{todos.map((todo) => (
<li key={todo._id}>{todo.task}</li>
))}
</ul>
</div>
);
};
export default App;

Step 7: Implementing Backend Routes for CRUD Operations

In your server.js file, add routes for creating, updating, and deleting todos:

// Create a new todo
app.post('/todos', async (req, res) => {
const newTodo = new Todo(req.body);
await newTodo.save();
res.json(newTodo);
});
// Update an existing todo
app.put('/todos/:id', async (req, res) => {
const updatedTodo = await Todo.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(updatedTodo);
});
// Delete a todo
app.delete('/todos/:id', async (req, res) => {
await Todo.findByIdAndRemove(req.params.id);
res.json({ message: 'Todo deleted successfully' });
});

Step 8: Adding Personal Flair with Custom CSS

Now that your MERN stack application is taking shape, it’s time to give it a personal touch with custom CSS. Let’s enhance the visual appeal and user experience by adding some styling. Follow these steps to create a customized look for your application:

8.1 Organize Your Styles

In the client/src directory, create a new folder named styles. Inside this folder, create a file named App.css for your application-wide styles.

/* App.css */
body {
font-family: 'Arial', sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #333;
}
ul {
list-style: none;
padding: 0;
}
li {
background-color: #fff;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
input[type="text"] {
padding: 10px;
font-size: 16px;
margin-right: 10px;
}
button {
padding: 10px;
font-size: 16px;
cursor: pointer;
background-color: #4caf50;
color: #fff;
border: none;
border-radius: 5px;
}
button:hover {
background-color: #45a049;
}

8.2 Link the Styles to Your Components

In the client/src directory, open the App.js file and import your custom styles:

//App.js
... (existing code)
import TodoForm from './TodoForm';
import './styles/App.css'; // Import the custom styles
const App = () => {
// ... (existing code)
return (
<div className="container">
<h1>MERN Stack Todo App</h1>
<TodoForm onAdd={addTodo} />
<ul>
{todos.map((todo) => (
<li key={todo._id}>{todo.task}</li>
))}
</ul>
</div>
);
};
export default App;

8.3 See Your Customized Application

Run your application and observe the enhanced visual appeal with your custom styles:

cd client
npm start

Visit http://localhost:3000 in your browser to see the changes.

Feel free to customize the styles further to match your preferences. Experiment with colors, fonts, and layout until you achieve the look that resonates with your vision for the MERN stack application. Your creativity is the limit!

This tutorial covers the initial steps of setting up a basic MERN stack application with a Node.js backend, MongoDB database, and a React frontend. Stay tuned for the continuation of this hands-on MERN stack development journey

--

--