Overview
An internal support desk where three roles interact with one queue. Reporters raise and track tickets, agents work and comment on them, administrators manage users and oversee the whole queue. Authentication is JWT-based and authorisation is enforced in middleware, so a role's boundaries are defined in one place rather than re-derived in each route handler.
Problem
Support requests arriving through email and chat have no state, no owner and no history. Nobody can answer who is handling a request, how long it has been open, or what was already tried.
Adding a database alone does not fix it. The moment three roles share one queue, the real problem becomes authorisation: who may reassign, who may close, who may see another person's ticket.
Business context
A support desk is a workflow tool before it is a data store. Its value is in making ownership and state explicit so that work stops being dropped.
It is also the point where an internal tool most often leaks: a missing authorisation check on one endpoint exposes every ticket in the system.
Solution
Three models — user, ticket and comment — with the comment thread attached to the ticket, so the conversation and the state live together rather than in someone's inbox.
Authentication middleware verifies a signed token and attaches the caller; role middleware then gates the route. Adding an endpoint means declaring which roles may reach it, not reimplementing the check.
Attachments are uploaded through Multer and stored on Cloudinary rather than on the application filesystem, which is what makes the service safe to run on ephemeral serverless instances.
An admin seed script creates the first administrator deterministically, so a fresh deployment has a defined starting state instead of requiring a manual database insert.
Architecture
Clients
Reporter
Raise and track
Support agent
Work and comment
Administrator
Users and oversight
Application
React frontend
Role-aware views
Serverless entrypoint
Vercel function
Access
JWT auth middleware
Verify · attach caller
Role middleware
Central RBAC
Domain
Tickets
Lifecycle and assignment
Comments
Threaded per ticket
Users
Profiles and roles
Persistence
MongoDB
Tickets · comments · users
Cloudinary
Attachments
Implementation
Routes are grouped by resource — auth, tickets, comments, users — with controllers kept thin and shared concerns in middleware.
Tokens are generated through a single utility so signing options and expiry are defined once instead of drifting between endpoints.
The Express application is exported through a dedicated serverless entrypoint so the same codebase runs locally as a server and on Vercel as a function.
No local disk writes: uploads stream to Cloudinary, which is a requirement rather than an optimisation on a platform where the filesystem does not persist between invocations.
Engineering challenges
Authorisation that does not drift
Per-route permission checks are the standard way these systems leak, because one handler eventually forgets. Expressing roles as middleware means an endpoint without an explicit policy is visibly missing one.
Stateless compute and file uploads
Serverless instances do not keep a filesystem. Uploading straight to external object storage is what allows attachments to work at all in that environment.
Running one Express app in two environments
Local development wants a long-lived server; the platform wants a handler. Separating the application from its entrypoint lets both consume the same code without a parallel implementation.
Key decisions
- Roles in middleware, not in handlers
- It makes authorisation auditable in one file and makes a missing policy conspicuous.
- External object storage for attachments
- It is the only correct choice on ephemeral compute, and it removes file serving from the application entirely.
- A deterministic admin seed
- A new environment should reach a known good state through a script, not through manual database edits nobody records.
Results
No production metrics are published for this project yet. I would rather show nothing here than a number I cannot stand behind — the architecture and the decisions above are the part worth reviewing.
Technology
Frontend
- React
- Vite
- Client routing
Backend
- Node.js
- Express
- REST API
Data
- MongoDB
- Mongoose
- Ticket / Comment / User models
Access
- JWT
- Auth middleware
- Role middleware
Media
- Multer
- Cloudinary
Deployment
- Vercel serverless entrypoint
Links
Contact
Have an AI product or workflow worth building?
Send me the problem — not the spec. If it’s a fit I’ll tell you how I’d approach it; if it isn’t, I’ll say so.
Faisalabad, Pakistan · PKT (UTC+5) · Working remotely