Community Marketplace App using MERN Stack
Building a community Marketplace App will help you understand the foundational concepts of full-stack development using the MERN(MongoDB, ExpressJS, React, NodeJS) stack. This tutorial will guide you to set up the backend server for the project and demonstrate the integration of frontend functionality with backend setup. This tutorial will teach you how to leverage mongoDB to create and store product profiles.
Output Preview: Let us have a look at how the final output will look like.
Prerequisites:
Approach to Create Community Marketplace App:
- Define a functional component named App in ‘App.js‘.
- Make a list of necessary dependencies and component and import them.
- Define Nav and ProductList components and wrap them inside in the App components to provide access to shared context data
- Create Seller.js page with form component.
- Use React Router to navigate between different pages.
- Use Axios to fetch data from backend server.
- Establish connections to the MongoDB database from the backend server using Mongoose or MongoDB native drivers.
Steps to Create a Backend Server:
Step 1: Create a new directory named backend.
mkdir backend
cd backend
Step 2: Create a server using the following command in your terminal.
npm init -y
Step 3: Install the necessary package in your server using the following command.
npm install express mongoose mongodb cors
Project Structure:
The updated dependencies in package.json file of backend will look like:
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.3",
"mongodb": "^6.3.0",
"mongoose": "^8.2.0",
}
Step 4: Create a file ‘server.js’ and set up the server.
Javascript
// server.js const express = require( 'express' ); const mongoose = require( 'mongoose' ); const cors = require( 'cors' ); const app = express(); const PORT = process.env.PORT || 5000; // MongoDB connection mongoose.connect( 'mongodb://localhost:27017/myapp' , { useNewUrlParser: true , useUnifiedTopology: true }) .then(() => console.log( 'Connected to MongoDB' )) . catch (err => console.error(err)); // Define Product Schema const productSchema = new mongoose.Schema({ name: { type: String, required: true }, description: String, price: { type: Number, required: true }, category: String, imageUrl: String, // Directly store image URL }); const Product = mongoose.model( 'Product' , productSchema); // Middleware for CORS app.use(cors()); // Middleware for parsing JSON bodies app.use(express.json()); // Route to fetch products app.get( '/product' , async (req, res) => { try { const products = await Product.find(); res.json(products); } catch (err) { console.error(err); res.status(500).json({ message: 'Server Error' }); } }); // Route to add new product app.post( '/product' , async (req, res) => { try { const { name, description, price, category, imageUrl } = req.body; const newProduct = new Product({ name, description, price, category, imageUrl, }); const savedProduct = await newProduct.save(); res.status(201).json(savedProduct); } catch (err) { console.error(err); res.status(500).json({ message: 'Server Error' }); } }); // Start the server app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); |
Start your server using the following command.
node server.js
Steps to Create the Frontend:
Step 1: Create the frontend repository named client in the main repository.
mkdir client
cd client
Step 2: Create React project using following command.
npx create-react-app .
Step 3: Install necessary dependencies in your application using following command.
npm install axios react-router-dom
Project Structure:
The updated dependencies in package.json file of frontend will look like:
"dependencies": {
"axios": "^1.6.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
Example: Create the files according to the project structure and write the following code.
CSS
/* styles.css */ body { font-family : Arial , sans-serif ; margin : 0 ; padding : 0 ; } .container { max-width : 800px ; margin : 20px auto ; padding : 0 20px ; } h 2 { margin-bottom : 20px ; } .product-list { list-style : none ; padding : 0 ; } .product-item { border : 1px solid #ccc ; padding : 10px ; margin-bottom : 10px ; border-radius: 5px ; } .navbar { background-color : #333 ; color : #fff ; padding : 10px 20px ; display : flex; justify- content : space-between; align-items: center ; } .navbar-brand { margin : 0 ; } .nav-links { list-style : none ; padding : 0 ; margin : 0 ; display : flex; } .nav-item { margin-right : 10px ; } .nav-link { color : #fff ; text-decoration : none ; } /* Form styles */ .form-input { width : 100% ; padding : 8px ; margin-bottom : 10px ; font-size : 16px ; border-radius: 5px ; border : 1px solid #ccc ; } .form-submit { background-color : #333 ; color : #fff ; border : none ; padding : 10px 20px ; cursor : pointer ; border-radius: 5px ; } .form-submit:hover { background-color : #555 ; } .product-list { display : flex; flex-wrap: wrap; gap: 10px ; } .product { flex: 1 1 calc( 33.33% - 20px ); border : 1px solid #333 ; padding : 3px ; } .break-line { width : 100% ; margin-top : 20px ; border : none ; border-top : 1px solid #ccc ; } .product-image { width : 300px ; height : 200px ; object-fit: cover; border-radius: 5px ; } |
Javascript
// App.js import React from 'react' ; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom' ; import Nav from './Nav.js' ; import ProductList from './ProductList.js' ; import Seller from './Seller.js' ; import './index.css' const App = () => { return ( <Router> <div> <Nav /> <Routes> <Route path= "/" element={<ProductList />} /> <Route path= "/seller" element={<Seller />} /> </Routes> </div> </Router> ); } export default App; |
Javascript
// Seller.js import React, { useState } from 'react' ; import axios from 'axios' ; const Seller = () => { const [formData, setFormData] = useState({ name: '' , description: '' , price: '' , category: '' , imageUrl: '' , }); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.post( 'http://localhost:5000/product' , formData); console.log(response.data); } catch (error) { console.error( 'Error:' , error); } } const handleChange = (e) => { setFormData({ ...formData, [e.target.name]: e.target.value }); } return ( <div> <h2>Become a Seller</h2> <form onSubmit={handleSubmit}> <input type= "text" name= "name" placeholder= "Product Name" onChange={handleChange} /> <input type= "text" name= "description" placeholder= "Description" onChange={handleChange} /> <input type= "number" name= "price" placeholder= "Price" onChange={handleChange} /> <input type= "text" name= "category" placeholder= "Category" onChange={handleChange} /> <input type= "text" name= "imageUrl" placeholder= "Image URL" onChange={handleChange} /> <button type= "submit" >Add Product</button> </form> </div> ); } export default Seller; |
Javascript
// ProductList.js import React, { useState, useEffect } from 'react' ; import axios from 'axios' ; import './index.css' const ProductList = () => { const [products, setProducts] = useState([]); useEffect(() => { fetchProducts(); }, []); const fetchProducts = async () => { try { const response = await axios.get( 'http://localhost:5000/product' ); setProducts(response.data); } catch (error) { console.error( 'Error:' , error); } } return ( <div className= "container" > <h2>Products</h2> <div className= "product-list" > {products.map((product, index) => ( <div key={product._id} className= "product" > <h3>{product.name}</h3> <img src={product.imageUrl} alt={product.name} className= "product-image" /> <p className= "product-description" > Description: {product.description} </p> <p className= "product-price" > Price: ${product.price} </p> <p className= "product-category" > Category: {product.category} </p> { /* Add a line break after every third product */ } {((index + 1) % 3 === 0) && (<hr key={index} className= "break-line" />)} <button>Add to cart</button> </div> ))} </div> </div> ); } export default ProductList; |
Javascript
// Nav.js import React from 'react' ; import { Link } from 'react-router-dom' ; const Nav = () => { return ( <nav className= "navbar" > <h1 className= "navbar-brand" > Marketplace </h1> <ul className= "nav-links" > <li className= "nav-item" > <Link to= "/" className= "nav-link" > Home </Link> </li> <li className= "nav-item" > <Link to= "/seller" className= "nav-link" > Become a Seller </Link> </li> </ul> </nav> ); } export default Nav; |
Start the project using the given command.
npm start
Output:
- Browser Output
- Output of data saved in database:
Contact Us