A fullβstack print management platform for campuses: students upload files, get instant pricing, pay, and track orders; admins manage queues, pricing, and service status.
- Instant price calculation with configurable rules (B/W, color, paper size, duplex, GST).
- Secure file uploads to Cloudinary with serverβside MIME validation and size limits.
- Student workflow: upload β configure β pay (Razorpay Checkout) β place order β email confirmation.
- Admin dashboard: queue management, status updates, revenue/usage metrics, urgent requests view, and day/hour queue prediction.
- Dynamic pricing management with adminβonly endpoints and versioned updates.
- Service status controls (open/close shop with reason) reflected across the app.
- Authentication: Google OAuth and email OTP flows; JWTβsecured APIs and role checks.
- Email notifications (order confirmation, order ready) via Nodemailer/SMTP.
- Productionβready Express hardening: Helmet, CORS, compression, and rate limiting.
- SPA build served by the backend in production (single Render service friendly).
Highβlevel overview of how the pieces fit together.
-
Technologies
- Frontend: React 18, Vite, Tailwind CSS, React Router, Redux Toolkit
- Backend: Node.js, Express, Mongoose
- Database: MongoDB (Atlas/local)
- Storage: Cloudinary (raw uploads)
- Auth: JWT, Google OAuth 2.0, OTP via email
- Payments: Razorpay Checkout (client) with server persistence of
paymentId
-
Interaction model
- Client calls REST APIs under
/api/*for auth, pricing, orders, admin, and service status. - Files are uploaded to the backend, validated, then streamed to Cloudinary; the secure URL is stored with the print job.
- On payment success, the client saves the Razorpay
paymentIdto the order. - Admins act on orders and service status via protected endpoints.
- Client calls REST APIs under
ββββββββββββββββββββ ββββββββββββββββββββββββββ
β React (Vite) β HTTPS β Express API β
β Tailwind, Redux ββββββββββββΆβ Auth / Orders / Admin β
ββββββββββ¬ββββββββββ βββββββββββββ¬βββββββββββββ
β β
β β Mongoose
β βΌ
Razorpay Checkout MongoDB Atlas
β β²
β β
βΌ β
User Payment Email (SMTP)
β²
β
βΌ
Cloudinary (files)
- React 18, Vite, Tailwind CSS, React Router, Redux Toolkit
- Node.js, Express, Mongoose
- MongoDB
- Cloudinary (raw file storage)
- Razorpay Checkout (client integration)
- Passport (Google OAuth 2.0), JWT
- Nodemailer (SMTP)
- Helmet, CORS, Compression, Expressβrateβlimit
Prerequisites:
- Node.js β₯ 18.18 < 21 (per backend
engines) - npm
- MongoDB connection string (Atlas/local)
- Cloudinary account (cloud name, API key/secret)
- SMTP credentials (for emails)
Clone the repository:
git clone https://github.com/AniketBansod/PrintHub.git
cd PrintHubInstall dependencies (root scripts run both apps in dev):
npm installCreate backend environment file Backend/.env:
# App / Server
PORT=5000
NODE_ENV=development
CLIENT_ORIGIN=http://localhost:5173
# Database
MONGO_URI=YOUR_MONGODB_URI
# Auth & Security
JWT_SECRET=your_jwt_secret
SESSION_SECRET=your_session_secret
ADMIN_KEY=your_admin_registration_key
# Cloudinary
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Email (SMTP)
EMAIL_USER=your_email_account
EMAIL_PASS=your_email_password_or_app_passwordRun the project in development (concurrently runs backend and client):
npm run devAlternatively, run separately:
# Terminal 1
cd Backend; npm run dev
# Terminal 2
cd client; npm run dev-
Development
- Frontend:
cd client; npm run dev(default at http://localhost:5173) - Backend:
cd Backend; npm run dev(default at http://localhost:5000)
- Frontend:
-
Production (local)
- Build SPA and serve from backend:
cd Backend; npm install; npm run build; npm start
- The Express server serves
client/distand APIs from the same port.
- Build SPA and serve from backend:
-
Docker
- This repository does not ship a Dockerfile. If you prefer containers, add one and deploy as a Docker service on Render. An example is included in the Deployment section.
-
Student
- Open the app, upload a document (PDF/DOC/DOCX/TXT/images)
- Choose options (pages, color, sides, size, copies); price updates instantly
- Pay via Razorpay Checkout; order is queued and a confirmation email is sent
- Track order until marked done; receive a βready for collectionβ email
-
Admin
- Review queues, mark orders done/cancelled, view stats, set pricing, toggle service status, and check urgent requests/predictions
All backend variables are defined in Backend/.env:
PORT: API port (defaults to 5000)CLIENT_ORIGIN: Allowed origins for CORS and OAuth redirects (commaβseparated for multiple)MONGO_URI: MongoDB connection stringJWT_SECRET: Secret for signing JWTsSESSION_SECRET: Session secret used during Google OAuthADMIN_KEY: Required to create admin users via/api/auth/admin-registerCLOUDINARY_*: Cloudinary credentials for uploadsEMAIL_USER,EMAIL_PASS: SMTP credentials for Nodemailer
Clientβside Razorpay publishes its key in the checkout snippet; store your key ID securely and expose only what Razorpay requires on the client.
Base URL: /api
-
Auth (
/api/auth)POST /send-otpβ Send signup OTPPOST /verify-otpβ Verify OTPPOST /registerβ Register user (requires verified email)POST /loginβ Login with email/passwordPOST /admin-registerβ Create admin (requiresADMIN_KEY)POST /request-password-resetβ Send reset OTPPOST /verify-reset-otpβ Verify reset OTPPOST /reset-passwordβ Reset passwordGET /profileβ Current user profile (JWT)GET /googleβGET /google/callbackβ Google OAuth 2.0
-
Pricing (
/api/pricing)GET /β Public pricing for studentsGET /adminβ Full pricing (admin)PUT /β Update pricing (admin)POST /calculateβ Calculate job price
-
Orders (
/api/orders)GET /β Get current user orders (JWT)POST /β Create order (JWT; blocked if service closed)PUT /:orderId/paymentβ AttachpaymentId, set status toprocessingPUT /:orderId/statusβ Admin updates order status
-
Uploads & Jobs
POST /uploadβ Upload a file to Cloudinary (multer memory storage)POST /printβ Upload + create a print job recordGET /cartβ List all print jobs (demo/dev)
-
Service Status
GET /service-statusβ Public status (open/closed + reason)GET /admin/service-statusβ Admin statusPUT /admin/service-statusβ Update status (admin)
-
Admin (
/api/admin)GET /overviewβ Stats: pending, users, revenue, todayβs jobs, month revenueGET /ordersβ List orders (summary)GET /orders/:orderIdβ Order details with print jobsGET /orders/status/:statusβ Orders by status (queue|done|cancelled)PUT /orders/:orderId/statusβ Update order status and email notificationGET /urgent-requestsβ Urgent/express or nearβdeadline ordersGET /queue-predictionβ Aggregated hour slots for next 48hGET /download/:printJobIdβ Signed Cloudinary URL redirect
The backend enables compression and rate limiting by default. Add APM/metrics if you need detailed throughput/latency numbers.
Backend/
server.js # Express app, routing, static serving, security
routes/ # auth, orders, admin, pricing
models/ # User, Order, PrintJob, Pricing, ServiceStatus
middleware/ # auth (JWT), serviceStatus check
services/ # emailService (Nodemailer)
constants/ # pricing defaults, allowed MIME types
build/client/ # copied SPA build (created at build time)
client/
src/ # React app (pages, components, contexts, slices)
public/ # Static assets
package.json (root) # Dev scripts to run client+server concurrently
- JWT auth on protected routes; role checks for admin endpoints
- Google OAuth 2.0 for social login; session used during OAuth flow
- Email OTP for signup and password reset with attempt limits and expiry
- Helmet, CORS (allowβlist via
CLIENT_ORIGIN), Compression, Rate limiting - Serverβside file type/size validation before uploading to Cloudinary
Important: The client saves Razorpay paymentId via /api/orders/:orderId/payment. Add serverβside signature verification (Razorpay webhook or callback verification) before treating a payment as final in production.
Monorepo tip: deploy the backend as a Web Service with the Backend directory as the root.
- Build Command:
npm install - Start Command:
npm start - Node Version: 18.x (Render detects from
engines) - Environment: add variables from the Configuration section
The backend postinstall builds the React client and copies it into Backend/build/client, and the server serves the SPA and APIs from a single service.
This repo does not include a Dockerfile. If you prefer Docker, add one similar to:
FROM node:18-alpine AS build
WORKDIR /app
COPY client ./client
WORKDIR /app/client
RUN npm ci && npm run build
FROM node:18-alpine
WORKDIR /app
COPY Backend ./Backend
COPY --from=build /app/client/dist ./client/dist
WORKDIR /app/Backend
RUN npm ci --omit=dev
ENV NODE_ENV=production
CMD ["npm", "start"]Then create a Render Web Service from the repo, set Docker build, and add the same env vars.
- Razorpay signature verification + webhooks for tamperβproof payments
- Endβtoβend tests (API + UI) and load testing
- Granular roles/permissions and audit logs
- Presigned upload flow with antivirus scanning
- Pagination and advanced filtering in admin lists
- Metrics/observability (req timing, error rates, job durations)
- Multiβprinter routing and device integration
- PWA enhancements (offline queue, installable app)
Distributed under the ISC License. See LICENSE for details.
- React, Vite, Tailwind CSS
- Node.js, Express, Mongoose, MongoDB
- Cloudinary, Razorpay, Nodemailer
- Shields.io for badges