JK
>LOADING // LOADING
INITIALIZING VIEW
Backend for a multi-restaurant food ordering platform supporting three user roles (customer, restaurant owner, admin), JWT authentication, menu management with Cloudinary image uploads, and order lifecycle tracking.
Acts as the backend for a restaurant ordering platform where customers browse menus from multiple restaurants, place orders, and track delivery status. Restaurant owners manage their menu items. Admins manage the system. The API supports ~15 endpoints across 5 domains with a modular monolith architecture.
| Technology | Version | Purpose | Why Chosen |
|---|---|---|---|
| Node.js | — | JavaScript runtime | Non-blocking I/O, large ecosystem |
| Express.js | 4.19.2 | HTTP framework | Minimal, flexible, well-documented |
| TypeScript | 5.5.4 | Type safety | Compile-time error catching, IDE support |
| MongoDB | — | Document database | Flexible schema, JSON-native, horizontal scaling |
| Mongoose | 8.5.3 | MongoDB ODM | Schema validation, middleware, query building |
| JWT (jsonwebtoken) | 9.0.2 | Authentication tokens | Stateless auth, industry standard |
| bcrypt | 5.1.1 | Password hashing | Adaptive hashing, salt rounds |
| Cloudinary | 2.4.0 | Image hosting/CDN | Managed service, CDN, image transformations |
| Multer | 1.4.5-lts.1 | File upload handling | Express-integrated, simple API |
| Method | Route | Purpose |
|---|---|---|
| GET | / | Health check / welcome |
| POST | /api/users/register | Register new user |
| POST | /api/users/login | Login user |
| POST | /api/admin/createAdmin | Create admin user |
| POST | /api/admin/adminlogin | Login admin |
| POST | /api/restaurant/createRestaurant | Register restaurant owner |
| POST | /api/restaurant/ownerLogin | Login restaurant owner |
| POST | /api/Menuitems/addItems | Create menu item with image |
| PUT | /api/Menuitems/:itemId | Update menu item |
| GET | /api/Menuitems/getAllItems | List all menu items |
| GET | /api/Menuitems/:itemId | Get single menu item |
| DELETE | /api/Menuitems/:itemId | Delete menu item |
| POST | /api/orders/createorder | Create order |
| POST | /api/orders/cancelorder/:orderId | Cancel order |
| GET | /api/orders/orderdetails/:orderId | Get order details |
| Column | Type | Notes |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| createdAt | Date | Auto (timestamps: true) |
| updatedAt | Date | Auto (timestamps: true) |
User accounts. Email is unique.
| Column | Type | Notes |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| userType | String | enum: ['admin', 'user', 'restOwner'] |
Admin accounts. Separate collection from users.
| Column | Type | Notes |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantEmail | String | Required |
| restaurantPwd | String | bcrypt hashed |
| restaurantName | String | Required |
| restaurantAddress | String | Required |
| restaurantPhoneNo | Number | Required, unique |
Restaurant owner accounts.
| Column | Type | Notes |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantId | ObjectId | No ref defined — .populate() won't work |
| itemName | String | Has typo: require instead of required |
| itemDescription | String | Has typo: require instead of required |
| itemPrice | Number | Has typo: require instead of required |
| itemImage | String | Cloudinary URL |
Menu items per restaurant. restaurantId lacks ref property — schema bug.
| Column | Type | Notes |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| customerId | ObjectId | ref: User |
| restaurantId | ObjectId | ref: restaurant |
| menuId | ObjectId | ref: MenuItems |
| orderQuantity | Number | No validation for positive values |
| orderDate | Date | Default: Date.now |
| orderStatus | String | enum: ['in process', 'transit', 'cancelled', 'delivered'] |
| orderBill | Number | Client-supplied — security concern |
Orders are client-supplied bill amounts — no server-side price calculation.
One-to-Many: Users→Orders, Restaurants→MenuItems, Restaurants→Orders, MenuItems→Orders. All via ObjectId references. No many-to-many relationships. menuitems.restaurantId lacks ref property.
Decision: Single Express.js application with domain-based folder structure
Why: Appropriate for project scale (~15 endpoints, single deployment)
Benefits: Simple deployment, easy debugging, low operational overhead, clear domain ownership
Trade-offs: Cannot scale domains independently, all modules share process, no service layer for reuse
Decision: Stateless JWT tokens with Authorization: Bearer header
Why: Standard for REST APIs, no session storage needed
Benefits: Stateless, no server-side session store, scales horizontally
Trade-offs: No server-side revocation, tokens valid until expiry even if user is deleted
Decision: Business logic resides directly in controllers
Why: Simplicity for small project, fewer files to navigate
Benefits: Fast development, fewer abstractions
Trade-offs: Untestable business logic, code duplication across auth controllers, hard to reuse logic
Decision: Menu item images uploaded to Cloudinary CDN
Why: Managed service avoids S3/MinIO setup, provides CDN and image transformations
Benefits: No infrastructure to manage, built-in CDN, free tier available
Trade-offs: Vendor lock-in, external dependency, cost at scale, latency for non-CDN regions
Decision: orderBill is sent by the client, not calculated server-side
Why: Likely intentional simplification for MVP
Benefits: Simpler server logic
Trade-offs: Critical security vulnerability — clients can manipulate order amounts
Decision: Manual if (!field) validation instead of Zod/Joi
Why: Simplicity, fewer dependencies
Benefits: No additional dependency, explicit control
Trade-offs: Inconsistent validation, no type inference from schemas, generic error messages