Overview
Forever is a MERN-stack e-commerce platform split into two independent applications that talk over a REST API: a Vite + Redux Toolkit storefront/admin SPA (client/) and an Express + MongoDB API (server/). Rather than a single monolith, each half owns its own build, its own Dockerfile, and its own deployment path — the storefront handles browsing, cart, and checkout, while the API owns auth, products, orders, and payments behind JWT-guarded routes.
That split pays off at deployment time: the whole stack runs as one docker compose up --build for local development or self-hosting, while client/ and server/ also each ship an independent vercel.json so they can be deployed as two separate serverless projects with no code changes between the two paths.
Two deployment targets, one codebase
Forever was built to run identically as a three-container Docker Compose
stack (client, server, MongoDB) or as two independent Vercel
deployments — the same client and server code ships to both, with only
environment variables (VITE_BASE_URL, CLIENT_URL) changing between them.
The storefront's collections page — search, category/type filters, and sorting over the product catalog.
Tech Stack
- React 18 with Vite (SWC plugin) as the build tool
- React Router DOM v6 for routing across public and admin areas
- Redux Toolkit and RTK Query for state management and API caching
- redux-persist for persisting auth state across reloads
- Tailwind CSS + PostCSS + Autoprefixer for styling
- react-icons, react-hot-toast, react-toastify for UI polish
- ESLint for linting
- Node.js + Express 4 (ES modules)
- MongoDB with Mongoose 8
- JWT (
jsonwebtoken) + bcrypt for authentication - Zod for request validation
- Multer for multipart file uploads
- Cloudinary for image storage and delivery
- Stripe and Razorpay SDKs for payments
- Helmet, CORS, cookie-parser, body-parser for security and parsing
- nodemon for development
- Docker + docker-compose (client, server, and MongoDB services)
- Vercel deployment configs for both apps, deployed independently
Feature Breakdown
Storefront
Search, category/type filters, and sorting over a paginated collections page; a product page with image gallery, sizes, and related items; a persistent cart; checkout via Stripe, Razorpay, or Cash-on-Delivery; and order history with tracking status.
Admin Dashboard
A /admin suite with analytics widgets, product CRUD (Cloudinary image
uploads), order status management, customer and category management, a
transactions view, and paginated contact-form messages — all gated behind
role-protected routes.
Backend Capabilities
JWT auth via cookies, Zod schema validation middleware, a centralized error handler, pagination on users/products/orders/contacts, a Multer → Cloudinary upload pipeline, and Stripe/Razorpay session creation and verification.
The admin dashboard — product, order, and customer management behind role-protected routes.
Architecture
User Journey
Discovery
The user lands on Home (/), rendered through RootLayout, and sees
featured collections, policies, and a newsletter box.
Browse & select
Filtering and sorting on /collections is fetched via RTK Query
(productApiSlice) from GET /api/v1/products. /collections/:id loads a
single product where the user picks a size and adds it to the cart.
Cart & auth
Cart state lives in Redux and is synced to the server via
cartApiSlice → /api/v1/cart. Unauthenticated users are routed to
/auth/sign-in or /auth/sign-up; on success a JWT cookie is set and
auth state is persisted with redux-persist.
Checkout & verification
/checkout posts shipping info and the chosen payment method (Stripe,
Razorpay, or COD) to /api/v1/orders. Online payments redirect to the
gateway and back to /verify, which confirms and finalizes the order.
Orders & admin
/orders lists the user's order history via orderApiSlice. A
privileged user instead lands in /admin/*, gated by AdminLayout, where
CRUD actions fan out to the same API slices.
Request Lifecycle (Server)
Every request funnels through the same pipeline before it ever reaches a model:
Requests enter server/src/app.js, pass through Helmet/CORS/cookie-parser, get routed to a controller, are validated by a per-resource Zod schema, touch Mongoose models, and return JSON. Errors from any stage funnel through a single errorHandler.middleware.js.
API Endpoints
Base URL: /api/v1. All protected routes require a valid JWT sent via cookie; admin-only routes additionally check the user's role.
| Resource | Mount point | Purpose |
|---|---|---|
| Auth | /api/v1/auth | Register, login, logout, session checks |
| Users | /api/v1/users | User listing (admin), profile, deletion |
| Products | /api/v1/products | CRUD, search, filters, pagination |
| Cart | /api/v1/cart | Get / update the authenticated user's cart |
| Orders | /api/v1/orders | Create, list, verify (Stripe/Razorpay), admin updates |
| Contact | /api/v1/contact | Submit and list contact messages |
Project Structure
Getting Started
Environment Variables
VITE_BASE_URL=http://localhost:8080/api/v1
VITE_APP_URL=http://localhost:5173
VITE_NODE_ENV=development
VITE_DEMO_ACCOUNT=demo@forever.comPORT=8080
NODE_ENV=development
MONGO_URI=mongodb://localhost:27017/forever
JWT_SECRET=your_jwt_secret
CLIENT_URL=http://localhost:5173
CLOUDINARY_NAME=...
CLOUDINARY_API_KEY=...
CLOUDINARY_API_SECRET=...
STRIPE_SECRET_KEY=...
STRIPE_PUBLIC_KEY=...
CURRENCY=usd
DELIVERY_CHARGE=10Running Locally
Requires Node.js 18+, Yarn, and MongoDB (local or Atlas) — or just Docker.
cd server
yarn install
yarn dev # starts on http://localhost:8080cd client
yarn install
yarn dev # starts on http://localhost:5173docker compose up --buildSpins up MongoDB, the Express API, and the built Vite client together.
Deployment
- Vercel — both
client/andserver/containvercel.jsonconfigs for independent deployments. - Docker Hub — the compose file references prebuilt images
naseemkhandev/forever-clientandnaseemkhandev/forever-server.
Frequently Asked Questions
See it in action
Explore the live storefront and admin dashboard at forever.naseemkhan.dev.
