Great idea 👍 — practicing multiple setups will prepare you for any company’s exam format.
Here’s another advanced project example with full setup.
🚀 Example 2: E-Commerce API Backend
A practical, advanced Node.js + Express + Database project that covers auth, CRUD, relationships, validation, middleware, and security.
📂 Project Structure
ecommerce-api/
│── src/
│ ├── config/
│ │ └── db.js
│ ├── controllers/
│ │ ├── authController.js
│ │ ├── productController.js
│ │ └── orderController.js
│ ├── middleware/
│ │ ├── authMiddleware.js
│ │ └── errorMiddleware.js
│ ├── models/
│ │ ├── User.js
│ │ ├── Product.js
│ │ └── Order.js
│ ├── routes/
│ │ ├── authRoutes.js
│ │ ├── productRoutes.js
│ │ └── orderRoutes.js
│ ├── app.js
│ └── server.js
│── .env
│── package.json
📦 Install Dependencies
npm init -y
npm install express bcryptjs jsonwebtoken dotenv mongoose
npm install joi helmet cors morgan winston
npm install nodemon --save-dev
⚙️ src/config/db.js
(MongoDB with Mongoose)
const mongoose = require("mongoose");
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI);
console.log("MongoDB Connected");
} catch (err) {
console.error(err.message);
process.exit(1);
}
};
module.exports = connectDB;
👤 src/models/User.js
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
role: { type: String, enum: ["Customer", "Admin"], default: "Customer" },
}, { timestamps: true });
module.exports = mongoose.model("User", userSchema);
📦 src/models/Product.js
const mongoose = require("mongoose");
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
price: { type: Number, required: true },
stock: { type: Number, default: 0 },
}, { timestamps: true });
module.exports = mongoose.model("Product", productSchema);
🛒 src/models/Order.js
const mongoose = require("mongoose");
const orderSchema = new mongoose.Schema({
customer: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
products: [
{
product: { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
quantity: { type: Number, required: true },
},
],
status: { type: String, enum: ["Pending", "Completed"], default: "Pending" },
}, { timestamps: true });
module.exports = mongoose.model("Order", orderSchema);
🔑 src/controllers/authController.js
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const User = require("../models/User");
exports.register = async (req, res, next) => {
try {
const { name, email, password, role } = req.body;
const hashed = await bcrypt.hash(password, 10);
const user = await User.create({ name, email, password: hashed, role });
res.status(201).json({ message: "User created", user });
} catch (err) {
next(err);
}
};
exports.login = async (req, res, next) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(401).json({ message: "Invalid credentials" });
const valid = await bcrypt.compare(password, user.password);
if (!valid) return res.status(401).json({ message: "Invalid credentials" });
const token = jwt.sign({ id: user._id, role: user.role }, process.env.JWT_SECRET, {
expiresIn: "1h",
});
res.json({ token });
} catch (err) {
next(err);
}
};
📦 src/controllers/productController.js
const Product = require("../models/Product");
exports.createProduct = async (req, res, next) => {
try {
const product = await Product.create(req.body);
res.status(201).json(product);
} catch (err) {
next(err);
}
};
exports.getProducts = async (req, res, next) => {
try {
const products = await Product.find();
res.json(products);
} catch (err) {
next(err);
}
};
🛒 src/controllers/orderController.js
const Order = require("../models/Order");
exports.createOrder = async (req, res, next) => {
try {
const order = await Order.create({ customer: req.user.id, products: req.body.products });
res.status(201).json(order);
} catch (err) {
next(err);
}
};
exports.getMyOrders = async (req, res, next) => {
try {
const orders = await Order.find({ customer: req.user.id }).populate("products.product");
res.json(orders);
} catch (err) {
next(err);
}
};
🔐 src/middleware/authMiddleware.js
const jwt = require("jsonwebtoken");
exports.authMiddleware = (req, res, next) => {
const token = req.headers["authorization"];
if (!token) return res.status(401).json({ message: "No token provided" });
try {
const decoded = jwt.verify(token.split(" ")[1], process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ message: "Invalid token" });
}
};
exports.roleMiddleware = (roles) => (req, res, next) => {
if (!roles.includes(req.user.role)) return res.status(403).json({ message: "Forbidden" });
next();
};
🚦 src/middleware/errorMiddleware.js
exports.errorHandler = (err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: err.message });
};
🌍 Routes
src/routes/authRoutes.js
const express = require("express");
const { register, login } = require("../controllers/authController");
const router = express.Router();
router.post("/register", register);
router.post("/login", login);
module.exports = router;
src/routes/productRoutes.js
const express = require("express");
const { createProduct, getProducts } = require("../controllers/productController");
const { authMiddleware, roleMiddleware } = require("../middleware/authMiddleware");
const router = express.Router();
router.post("/", authMiddleware, roleMiddleware(["Admin"]), createProduct);
router.get("/", getProducts);
module.exports = router;
src/routes/orderRoutes.js
const express = require("express");
const { createOrder, getMyOrders } = require("../controllers/orderController");
const { authMiddleware } = require("../middleware/authMiddleware");
const router = express.Router();
router.post("/", authMiddleware, createOrder);
router.get("/", authMiddleware, getMyOrders);
module.exports = router;
🚀 src/app.js
const express = require("express");
const dotenv = require("dotenv");
const helmet = require("helmet");
const morgan = require("morgan");
const authRoutes = require("./routes/authRoutes");
const productRoutes = require("./routes/productRoutes");
const orderRoutes = require("./routes/orderRoutes");
const { errorHandler } = require("./middleware/errorMiddleware");
dotenv.config();
const app = express();
app.use(express.json());
app.use(helmet());
app.use(morgan("dev"));
app.use("/api/auth", authRoutes);
app.use("/api/products", productRoutes);
app.use("/api/orders", orderRoutes);
app.use(errorHandler);
module.exports = app;
🖥️ src/server.js
const app = require("./app");
const connectDB = require("./config/db");
const PORT = process.env.PORT || 5000;
connectDB();
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
🔑 .env
PORT=5000
MONGO_URI=mongodb://localhost:27017/ecommerce
JWT_SECRET=supersecretkey
✅ This E-Commerce API project tests:
-
Authentication (JWT + Roles)
-
CRUD (Products, Orders)
-
Database Relations (User ↔ Orders, Orders ↔ Products)
-
Middleware (Auth, Role-based access, Error handling)
-
Security (Helmet, hashed passwords)
Would you like me to now build a step-by-step 3-hour practice plan (like a roadmap: 30 min DB setup, 1 hr Auth, 1 hr Orders/Products, 30 min extras) for this project, so you can simulate the exam under time pressure?
Tags
Node js