Full‑stack pharmacy inventory and sales dashboard. The frontend is built with React + TypeScript + Vite and deployed on Vercel. The backend is a Flask + SQLAlchemy API using SQLite, deployed on Render.com.
- Frontend (Vercel):
- React + TypeScript + Vite SPA in the
frontend/folder. - Talks to the backend via REST endpoints under the
/apiprefix. - In local development, Vite proxies
/apito the Flask backend.
- React + TypeScript + Vite SPA in the
- Backend (Render.com):
- Flask application in the
backend/folder. - Uses SQLAlchemy ORM with a SQLite database (
pharmacy.dbinbackend/). - Exposes JSON APIs under
/api/dashboard/*and/api/inventory/*. - Seeds initial demo data on startup and keeps medicine status fields in sync.
- Flask application in the
- Local development
- Backend:
http://localhost:5000 - Frontend (Vite dev):
http://localhost:5173 - Proxy: Vite proxies
/apitohttp://localhost:5000(seefrontend/vite.config.ts).
- Backend:
- Production
- Backend (Render):
https://pharmacy-backend.onrender.com- Replace this with your actual Render service URL if different.
- Frontend (Vercel):
https://your-frontend-app.vercel.app- Configure Vercel rewrites or environment variables so that frontend
/api/*calls reach the Render backend.
- Configure Vercel rewrites or environment variables so that frontend
- Backend (Render):
From the backend/ directory:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 app.py- Base URL:
http://localhost:5000 - API prefix: All endpoints are under
/api/*. - Database: A SQLite file
pharmacy.dbis created automatically inbackend/. - Error handling:
- All responses follow a common envelope:
{
"success": true,
"data": { "... endpoint specific ..." },
"error": null
}On errors:
{
"success": false,
"data": null,
"error": {
"code": "validation_error",
"message": "Invalid request body.",
"details": { "... optional structured details ..." }
}
}From the frontend/ directory:
npm install
npm run dev- Dev server:
http://localhost:5173 - API access:
- All frontend API clients call relative paths like
/api/inventory/medicines. - During local development, these are proxied to
http://localhost:5000.
- All frontend API clients call relative paths like
- Source of truth:
openapi.yamlat the project root. - Spec version: OpenAPI 3.0.3.
- Groups:
- Inventory:
/api/inventory/* - Dashboard:
/api/dashboard/*
- Inventory:
- Top‑level response shape:
- All success responses:
success: truedata: <endpoint specific payload>error: null
- All error responses:
success: falsedata: nullerror: { code, message, details? }
- All success responses:
You can explore the contract with any OpenAPI viewer, for example:
npx @redocly/cli preview-docs openapi.yamlor by importing openapi.yaml into Swagger UI, Postman, or Insomnia.
-
Inventory
- GET
/api/inventory/overview
Returns overall inventory metrics (total items, active stock, low stock, total inventory value). - GET
/api/inventory/medicines
Lists medicines with optional filters:search,status,category. - POST
/api/inventory/medicines
Creates a new medicine record. - PUT
/api/inventory/medicines/{medicine_id}
Updates an existing medicine record (partial updates allowed). - PATCH
/api/inventory/medicines/{medicine_id}/status
Overrides the computed status of a medicine (active,low_stock,expired,out_of_stock).
- GET
-
Dashboard
- GET
/api/dashboard/today-sales-summary
Returns total sales amount, percentage change vs. yesterday, and order count for today. - GET
/api/dashboard/items-sold-today
Returns the total number of items sold today. - GET
/api/dashboard/low-stock-items
Returns low‑stock medicines (supportslimitquery param). - GET
/api/dashboard/purchase-orders-summary
Returns pending purchase order count and total purchase order value. - GET
/api/dashboard/recent-sales
Returns the most recent sales (supportslimitquery param).
- GET
For complete request/response schemas, consult openapi.yaml.
-
Backend (Render.com)
- Build & runtime:
- Python version should match your local environment.
- Install dependencies from
backend/requirements.txt.
- Start command (examples):
- Simple:
python app.py - Or with Gunicorn:
gunicorn 'app:create_app()'
- Simple:
- Ensure the working directory is
backend/so the SQLite file and imports resolve correctly.
- Build & runtime:
-
Frontend (Vercel)
- Build command:
npm run build(fromfrontend/). - Output directory:
frontend/dist. - Configure environment or rewrites so that
/api/*requests from the frontend are routed to the Render backend (e.g., via Vercel rewrites or an exposed public backend URL).
- Build command: