FoodNest is a full-stack food ordering platform built around a realistic three-role workflow: customers place orders, restaurants prepare and hand them off, and delivery partners accept, deny, and complete deliveries.
The application demonstrates end-to-end product thinking across authentication, role-based routing, MongoDB data modeling, realtime status updates, restaurant operations, delivery assignment, customer feedback, analytics, and a mock payment flow.
- Role-based dashboards for customers, restaurants, and delivery partners.
- JWT authentication with protected backend routes and frontend route guards.
- MongoDB/Mongoose schemas for users, restaurants, menus, and orders.
- Multi-step order lifecycle with backend transition validation.
- Delivery accept/deny workflow where denied orders remain available to other partners.
- Realtime order updates using Socket.IO.
- Restaurant menu management, order processing, analytics, and feedback views.
- Customer cart, coupons, mock checkout, order history, and delivery partner details.
- OpenStreetMap embeds for tracking and delivery map views.
- Seeded Indian restaurant catalog for quick local demos.
| Area | Technologies |
|---|---|
| Frontend | React 19, Vite 8, React Router DOM 7, Tailwind CSS |
| Frontend Libraries | Axios, Framer Motion, Swiper, Lucide React, React Hot Toast, Socket.IO Client |
| Backend | Node.js, Express 5, JWT, bcryptjs, Socket.IO |
| Database | MongoDB, Mongoose |
| Tooling | ESLint, Nodemon, Docker Compose |
| Integrations | Mock Razorpay-style payment endpoints, OpenStreetMap embeds |
- Browse restaurants and search/filter dishes.
- View restaurant menus and manage cart quantities.
- Apply local demo coupons and offers.
- Place orders through a mock payment flow.
- Track order status from placement to delivery.
- View delivery partner details after acceptance.
- Submit restaurant feedback and ratings.
- Manage menu items and availability.
- Create local promotional offers.
- Accept or reject incoming orders.
- Move orders through preparation and pickup readiness.
- View delivery partner details after a partner accepts.
- Hand orders to delivery partners with
Delivered to agent. - Track order history, revenue, top items, and customer feedback.
- View available pickups once restaurants mark orders ready.
- Accept or deny delivery requests.
- See restaurant and customer contact details.
- Track assigned deliveries.
- Complete delivery after restaurant handoff.
The main workflow is validated on the backend:
PLACED
-> RESTAURANT_ACCEPTED
-> PREPARING
-> READY_FOR_PICKUP
-> DELIVERY_ASSIGNED
-> DELIVERED_TO_AGENT
-> DELIVEREDTerminal alternatives:
CANCELLED
RESTAURANT_REJECTED- Customer places an order.
- Restaurant accepts and prepares the order.
- Restaurant marks it
Ready for pickup. - Delivery partners see it under available pickups.
- A delivery partner accepts or denies it.
- If denied, the order is hidden from that partner but remains available to others.
- If accepted, customer and restaurant can see delivery partner details.
- Restaurant clicks
Delivered to agent. - Customer sees the order as on the way.
- Delivery partner clicks
Delivered. - The order is completed for every role.
React + Vite Client
|
| REST API calls with Axios
| Socket.IO realtime events
v
Express API Server
|
| Mongoose models/controllers
v
MongoDBclient/src/
App.jsx # Role guarded routes
main.jsx # React entry point
index.css # Tailwind and shared styling
hooks/useFoodNest.js # Central app state, API calls, realtime updates
components/TopNavbar.jsx # Shared navigation and auth UI
components/ProfilePanel.jsx # Profile and summary panel
pages/UserPages.jsx # Customer screens
pages/RestaurantPages.jsx # Restaurant screens
pages/DeliveryPages.jsx # Delivery partner screens
data/fallbackRestaurants.js # Offline fallback restaurant dataserver/src/
server.js # Server startup, DB connection, Socket.IO
app.js # Express app and route mounting
config/db.js # MongoDB connection
config/seedData.js # Initial restaurant/menu seed data
middleware/auth.js # JWT auth and role checks
models/ # Mongoose schemas
routes/ # Express routes
controllers/ # Business logicfoody/
README.md
docker-compose.mongo.yml
client/
package.json
vite.config.js
tailwind.config.js
src/
server/
package.json
src/- Node.js
- npm
- MongoDB or Docker Desktop
Using Docker:
docker compose -f docker-compose.mongo.yml up -dMongoDB runs at:
mongodb://127.0.0.1:27017Create server/.env:
PORT=5000
MONGODB_URI=mongodb://127.0.0.1:27017/foodnest
JWT_SECRET=replace_with_a_strong_secret
CLIENT_URL=http://localhost:5173Run the API:
cd server
npm install
npm run devBackend:
http://localhost:5000Health check:
GET http://localhost:5000/api/healthCreate client/.env:
VITE_API_URL=http://localhost:5000/apiRun the client:
cd client
npm install
npm run devFrontend:
http://localhost:5173On first backend startup, the app seeds:
- 15 Indian restaurants
- menu items for each restaurant
- a default restaurant owner
Default seeded restaurant owner:
Email: owner@foody.local
Password: password123
Role: restaurantYou can also register through the UI as:
userrestaurantdelivery
| Route | Description |
|---|---|
/user |
Customer home |
/restaurants |
Restaurant search and filters |
/restaurant/:id |
Restaurant menu |
/user/cart |
Cart and checkout |
/user/orders |
Order history |
/user/orders/:id |
Order details, delivery details, feedback |
/user/tracking |
Latest order tracking |
/profile |
Profile summary |
| Route | Description |
|---|---|
/restaurant/menu |
Menu management and offers |
/restaurant/current-orders |
Active order workflow |
/restaurant/orders |
Order history |
/restaurant/orders/:id |
Order detail |
/restaurant/analytics |
Analytics and feedback |
/profile |
Profile summary |
| Route | Description |
|---|---|
/delivery/orders |
Available pickups and assigned deliveries |
/delivery/maps |
Delivery map view |
/profile |
Profile summary |
Base URL:
http://localhost:5000/api| Module | Endpoints |
|---|---|
| Auth | POST /auth/register, POST /auth/login |
| Restaurants | GET /restaurants, GET /restaurants/:id, POST /restaurants, GET /restaurants/owner/me, GET /restaurants/owner/analytics |
| Menu | GET /menu/restaurant/:restaurantId, POST /menu, PATCH /menu/:id, DELETE /menu/:id |
| Orders | POST /orders, GET /orders/me, PATCH /orders/:id/status |
| Delivery | GET /delivery/available-orders, POST /delivery/orders/:id/accept, POST /delivery/orders/:id/decline |
| Payment | POST /payment/create-order, POST /payment/verify |
| Model | Purpose |
|---|---|
User |
Stores customer, restaurant owner, and delivery partner accounts |
Restaurant |
Stores restaurant profile, owner, cuisine, rating, and location data |
MenuItem |
Stores restaurant menu items, pricing, availability, and category |
Order |
Stores order items, amount, customer, restaurant, delivery partner, status, payment state, and delivery denial state |
Persistent data is stored in MongoDB:
- users
- restaurants
- menu items
- orders
- delivery accept/deny state
Some UI/demo state is currently stored in browser localStorage:
| Key | Purpose |
|---|---|
foodnest-theme |
Selected theme |
foodnest-location |
Selected delivery city |
foodnest-restaurant-offers |
Local offer data |
foodnest-order-coupons |
Local coupon records |
foodnest-feedback |
Local customer feedback |
Socket.IO is used to broadcast order changes.
Server:
server/src/server.jsClient:
client/src/hooks/useFoodNest.jsEvents:
order:created
order:status-updatedFrontend:
cd client
npm run lint
npm run buildBackend syntax checks:
cd server
node -c src/server.js
node -c src/app.js
node -c src/controllers/orderController.js
node -c src/controllers/deliveryController.jsThis project can be deployed as a single Node web service that serves both the API and the built Vite frontend.
- App hosting: Render web service
- Database: MongoDB Atlas or any hosted MongoDB instance
A root render.yaml is included for Render Blueprint deploys. It:
- installs
serverandclientdependencies - builds the frontend with
VITE_API_URL=/api - starts the Express server from
server/src/server.js - serves the built frontend from Express in production
MONGODB_URIJWT_SECRETCLIENT_URL
For a single-service Render deploy, set:
VITE_API_URL=/api
CLIENT_URL=https://your-render-service-url.onrender.com- Push this repo to GitHub.
- Create a MongoDB Atlas database and copy its connection string.
- In Render, choose
New > Blueprintand connect the repo. - Render will detect the root
render.yaml. - Provide values for:
MONGODB_URICLIENT_URL
- Deploy the Blueprint.
- Open
https://your-service-url/api/healthto confirm the backend is live. - Open the root site URL to confirm the frontend is being served by Express.
- The first backend startup seeds demo restaurants if the database is empty.
- Local development still uses separate frontend and backend servers.
- If you prefer separate frontend/backend hosting, you can still deploy them independently by pointing
VITE_API_URLat your backend's public/apiURL.
- Persist auth sessions across page refreshes.
- Move feedback, coupons, and offers from localStorage to MongoDB.
- Add stronger backend ownership checks for order status updates.
- Integrate a real payment gateway.
- Add live driver GPS tracking and route calculation.
- Add automated API and UI tests.
- Add image upload support for restaurants and menu items.