Spaces:
Runtime error
title: Inventory Pro (Monolith)
emoji: π¦
colorFrom: gray
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
Inventory Pro
Single-domain deployment of a MERN inventory app on a Hugging Face Docker Space.
Inventory Pro β MERN (Assignment)
A full-stack inventory app that hits the assignment spec end-to-end:
- π Search & filter, π₯ Import / π€ Export CSV, βοΈ inline row editing, π§Ύ inventory history
- π Clean, responsive UI (table on desktop, cards on mobile)
- π§° Robust CSV parser (BOM, comma/semicolon/tab),optimistic updates
- π Production-friendly CORS, Express v5 compatible preflight
- βοΈ Ready to deploy: Backend β Render, Frontend β Netlify
Tech Stack
- Backend: Node.js, Express v5, Mongoose, Multer, csv-parse, json2csv, express-validator, Helmet, Morgan, CORS
- Frontend: React + TypeScript + Vite, Tailwind CSS, @tanstack/react-query v5, axios, lucide-react
- Database: MongoDB (Atlas or local)
Project Structure
inventory-pro/
backend/
src/
config/
controllers/
middleware/
models/
routes/
utils/
server.js
.env
package.json
frontend/
src/
components/
lib/
App.tsx
main.tsx
index.css
.env
index.html
netlify.toml # (optional, for Netlify)
package.json
README.md
Prerequisites
- Node.js 18+ (recommended 20+)
- MongoDB: Atlas connection string OR local
mongod
1) Run Locally
A) Backend
- Create
backend/.env:
PORT=4000
# Choose ONE:
# MONGODB_URI=mongodb+srv://<username>:<password>@cluster0.no4gl81.mongodb.net/inventorydb?retryWrites=true&w=majority&appName=Cluster0
MONGODB_URI=mongodb://127.0.0.1:27017/inventorydb
# Allow both common dev origins
CORS_ORIGIN=http://localhost:5173,http://127.0.0.1:5173
If your password has special characters (
@,#,!, etc.), URL-encode them (@β%40).
- Install & run:
cd backend
npm i
npm run dev
Expected log:
β
MongoDB connected
π API running on http://localhost:4000
Health checks in browser:
- http://localhost:4000/health β
{"ok":true,"db":"connected"} - http://localhost:4000/api/products β JSON list
Express v5 note: Preflight is handled safely (no wildcard
*route needed).
B) Frontend
- Create
frontend/.env:
VITE_API_BASE=http://localhost:4000
- Install & run:
cd frontend
npm i
npm run dev
Open the app (Vite prints the URL, usually http://localhost:5173).
- Top-right API / DB pills should be green β when backend is running.
- Hover them to see the API base URL in use.
2) CSV Format (Import/Export)
Headers (required):
name,unit,category,brand,stock,status,image
statusis optional; if omitted, itβs derived fromstock(0 β OUT_OF_STOCK, >0 β IN_STOCK)- Parser accepts comma, semicolon, or tab delimited CSV
- BOM/Excel CSVs are handled
Example:
name,unit,category,brand,stock,status,image
Coffee Beans,kg,Beverages,Acme,50,IN_STOCK,https://picsum.photos/seed/coffee/200
Tea Bags,box,Beverages,Acme,0,OUT_OF_STOCK,https://picsum.photos/seed/tea/200
3) Quick Tests (curl / PowerShell)
Create a CSV quickly (PowerShell):
@'
name,unit,category,brand,stock,status,image
Coffee Beans,kg,Beverages,Acme,50,IN_STOCK,https://picsum.photos/seed/coffee/200
Tea Bags,box,Beverages,Acme,0,OUT_OF_STOCK,https://picsum.photos/seed/tea/200
Sugar,kg,Grocery,SweetCo,100,IN_STOCK,https://picsum.photos/seed/sugar/200
Milk,litre,Dairy,DairyBest,20,IN_STOCK,https://picsum.photos/seed/milk/200
'@ | Set-Content -Encoding UTF8 ".\products.csv"
Import:
curl.exe -s -X POST "http://localhost:4000/api/products/import" -F "file=@products.csv"
# β {"addedCount":4,"skipped":[...if duplicates...]}
List:
curl.exe -s "http://localhost:4000/api/products?page=1&limit=10"
Search (assignment alias):
curl.exe -s "http://localhost:4000/api/products/search?name=Tea"
Update stock (PUT):
# get first id
$resp = Invoke-RestMethod -Uri "http://localhost:4000/api/products?limit=1" -Method GET
$id = $resp.data[0]._id
Invoke-RestMethod -Uri "http://localhost:4000/api/products/$id" -Method PUT -ContentType "application/json" -Body '{"stock":75}'
History:
curl.exe -s "http://localhost:4000/api/products/<id>/history"
Export:
curl.exe -L "http://localhost:4000/api/products/export" -o exported.csv
4) API Reference
Base URL (dev): http://localhost:4000/api
| Method | Path | Description |
|---|---|---|
| GET | /products |
List (pagination, sorting; filters name, category) |
| GET | /products/search |
Alias of list supporting ?name= |
| POST | /products/import |
Import CSV (multipart: file) |
| GET | /products/export |
Export all products as CSV |
| PUT | /products/:id |
Update editable fields (validates) |
| GET | /products/:id/history |
Inventory change logs (sorted desc) |
5) Assignment Mapping (Scoring)
Frontend (50 pts)
- Search bar (
/api/products/search?name=alias) + category filter β - βAdd New Productβ button (CSV one-row import) β
- Import/Export buttons aligned right (Export downloads; Import uploads & refreshes) β
- Products table columns: Image, Name, Unit, Category, Brand, Stock, Status, Actions β
- Stock labels: green βIn Stockβ when
>0, red βOut of Stockβ when0β - Actions: Edit/Delete; inline editing with Save β PUT
/api/products/:idβ - Table updates without full page refresh (optimistic) β
- Inventory history sidebar (fetch logs desc by date) β
- Responsive/mobile layout β
Backend (50 pts)
- Import CSV: accept file, parse columns, insert only new, return
addedCount+skipped(duplicate info for editing) β - Export CSV: returns all products β
- Products list: JSON with pagination & sorting β
- Update product: validation (unique name, numeric stock, status enum), updates only editable fields β
- Inventory history: logs stock changes; fetch API returns desc β
6) Deployment
A) Backend β Render
Push repo to GitHub.
Render: New β Web Service β connect
backend/Build Command:
npm installStart Command:node src/server.jsEnvironment variables:
MONGODB_URIβ your Atlas URI (e.g.,mongodb+srv://.../inventorydb?...)CORS_ORIGINβhttps://<your-netlify>.netlify.app- (Optionally add dev:
http://localhost:5173,http://127.0.0.1:5173)
- (Optionally add dev:
Deploy. Verify:
https://<render-app>.onrender.com/healthβ{ "ok": true, "db": "connected" }.
Express reads
process.env.PORTautomatically on Render.
B) Frontend β Netlify
- In
frontend/.envset:
VITE_API_BASE=https://<render-app>.onrender.com
- (Optional) Add
frontend/netlify.toml:
[build]
command = "npm run build"
publish = "dist"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Netlify β New site from Git
- Base directory:
frontend - Build command:
npm run build - Publish directory:
dist - Env var:
VITE_API_BASE=https://<render-app>.onrender.com
- Base directory:
7) Troubleshooting
Frontend βfailed to fetchβ / red API pill
- Backend not running or URL mismatch. Check
frontend/.envand restartnpm run dev. - CORS: ensure your frontend origin is in
CORS_ORIGIN.
- Backend not running or URL mismatch. Check
Import says βNo valid rows found in CSVβ
- Headers must match exactly:
name,unit,category,brand,stock,status,image. - At least
name,unit,categorymust be non-empty for a row to import. - Excel CSVs with semicolons are supported.
- Headers must match exactly:
History not updating
- Only changes to
stockcreate history entries.
- Only changes to
8) Scripts
Backend
npm run dev # nodemon dev server
npm start # node src/server.js
Frontend
npm run dev # Vite dev server
npm run build # production build
npm run preview # serve built app locally
License
MIT