An intelligent support ticket management system powered by AI that streamlines customer support workflows with smart ticket routing, automated analysis, and role-based access control.
- Intelligent Ticket Management: Create, track, and resolve support tickets efficiently
- AI-Powered Analysis: Automatic ticket categorization and suggested responses
- Role-Based Access Control: Support for Users, Moderators, and Admins
- Skills-Based Assignment: Match tickets with moderators based on expertise
- Real-time Updates: Live ticket status updates and notifications
- Responsive Design: Works seamlessly on desktop and mobile devices
- Users: Submit tickets, track progress, communicate with support
- Moderators: Handle tickets, provide support, manage resolutions (with skill-based matching)
- Admins: Full system access, user management, analytics
- Homepage Landing Page: Public homepage with clear signup/signin buttons for new users
- Role Selection During Signup: Users can choose to become regular users or moderators
- Skills Management: Moderators can add their expertise areas during signup
- Self-Service Profile Management: Moderators can update their skills anytime after account creation
- Post-Signup Profile Setup: New moderators are guided to set up their profile after registration
- Enhanced Navigation: Improved navbar with better button visibility and user experience
- About Page: Comprehensive information about the platform and its features
- Mobile-Optimized Interface: Enhanced mobile navigation and responsive design
- Intelligent Skills-Based Assignment: Tickets automatically matched to moderators based on skills
- API Retry Logic: Frontend automatically retries failed requests for better reliability
- Framework: React 18+ with Vite
- Styling: Tailwind CSS with custom components
- State Management: React Hooks
- Routing: React Router DOM v6
- Build Tool: Vite with hot reload
- React 18+ with functional components and hooks
- Vite for fast development and optimized builds
- Tailwind CSS for utility-first styling
- DaisyUI for pre-built component themes
- React Router DOM v6 for client-side routing
- Custom API client with automatic retry logic and error handling
- Safe storage utilities with localStorage fallbacks for reliability
- Node.js with Express.js framework
- MongoDB with Mongoose ODM for data modeling
- JWT (jsonwebtoken) for secure authentication
- Bcrypt for password hashing and security
- CORS middleware for cross-origin request handling
- Inngest for event-driven architecture and background jobs
- Custom AI integration for ticket analysis and suggestions
- ESLint for code quality and consistency
- Vite HMR for instant development feedback
- Git for version control
- Render for backend deployment
- Netlify for frontend deployment and CDN
- Node.js 18+ and npm
- MongoDB database
- Git
cd ai-ticket-assistant
npm install
cp .env.example .env  # Configure your environment variables
npm start  # Runs on http://localhost:4000cd ai-ticket-frontend
npm install
npm run dev  # Runs on http://localhost:5173# Backend (.env)
MONGODB_URI=your_mongodb_connection_string
ACCESS_TOKEN_SECRET=your_jwt_secret
INNGEST_EVENT_KEY=your_inngest_key
OPENAI_API_KEY=your_openai_key  # For AI features
# Frontend (automatically detected)
VITE_API_URL=http://localhost:4000/api  # For development- Frontend: https://aiagentticket.netlify.app
- Backend API: https://ticketmate-ai.onrender.com/api
- Health Check: https://ticketmate-ai.onrender.com/health
# Frontend (.env.production or Netlify Environment)
VITE_API_URL=https://ticketmate-ai.onrender.com/api
VITE_SERVER_URL=https://ticketmate-ai.onrender.com/api
# Backend (Render Environment Variables)
MONGO_URL=your_production_mongodb_uri
ACCESS_TOKEN_SECRET=your_production_jwt_secret
CLIENT_URL=https://aiagentticket.netlify.app
SERVER_PORT=4000
NODE_ENV=productionThe backend is configured to accept requests from:
- Local development: http://localhost:5173,http://localhost:3000
- Production: https://aiagentticket.netlify.app,https://ticketmate-ai.netlify.app
- Backend (Render): Auto-deploys from main branch
- Frontend (Netlify): Auto-deploys from main branch with build command npm run build
- Visit homepage → Click "Get Started" or "Sign Up"
- Choose role (User/Moderator) during signup
- If Moderator: Automatically redirected to profile page to add skills
- If User: Redirected to tickets dashboard to create first ticket
- Login → Navigate to "Profile" in navbar
- Add Skills: Type skill name and press Enter or click "Add Skill"
- Remove Skills: Click × on any skill tag to remove
- Save Changes: Skills are automatically saved and persist across sessions
- Skills Usage: Added skills are used for intelligent ticket assignment
- User creates ticket → AI automatically analyzes and generates helpful notes
- Auto-assignment to moderator based on skills match and availability
- Moderator handles ticket → Can use AI-suggested replies for faster responses
- Resolution tracking → Status updates, user notifications, resolution time tracking
- Development: http://localhost:4000/api
- Production: https://ticketmate-ai.onrender.com/api
All protected endpoints require a Bearer token in the Authorization header:
Authorization: Bearer <token>
{
  _id: string
  email: string
  password: string (hashed)
  role: "user" | "moderator" | "admin"
  skills?: string[]
  createdAt: Date
  updatedAt: Date
}{
  _id: string
  title: string
  description: string
  status: "TODO" | "open" | "in-progress" | "resolved" | "closed" | "cancelled"
  priority?: "low" | "medium" | "high"
  createdBy: User | string
  assignedTo?: User | string
  assignedAt?: Date
  resolvedAt?: Date
  helpfulNotes?: string // AI-generated analysis
  replyCanbeGiven?: string[] // AI-suggested replies
  relatedSkills?: string[]
  tags?: string[]
  replies: Reply[]
  createdAt: Date
  updatedAt: Date
}{
  message: string;
  author: User | string;
  createdAt: Date;
}Create a new user account with role selection and optional skills.
Request Body:
{
  "email": "user@example.com",
  "password": "password123",
  "role": "user", // "user" or "moderator" (default: "user")
  "skills": ["JavaScript", "Customer Support", "Network Administration"] // optional, for moderators
}Response:
{
  "token": "jwt_token_here",
  "user": {
    "_id": "user_id",
    "email": "user@example.com",
    "role": "user",
    "skills": [],
    "createdAt": "2024-01-01T00:00:00.000Z"
  },
  "message": "User created successfully"
}Status Codes:
- 201- User created successfully
- 400- Invalid input data (invalid email, weak password, invalid role, invalid skills format)
- 409- User already exists
Validation Rules:
- Email must be valid format
- Password must be at least 6 characters
- Role must be "user" or "moderator"
- Skills must be an array of non-empty strings (optional)
Authenticate user and get access token.
Request Body:
{
  "email": "user@example.com",
  "password": "password123"
}Response:
{
  "token": "jwt_token_here",
  "user": {
    "_id": "user_id",
    "email": "user@example.com",
    "role": "user"
  }
}Status Codes:
- 200- Login successful
- 401- Invalid credentials
- 400- Invalid input data
Update current user's profile (skills). New Feature: Self-Service Profile Management
Headers:
Authorization: Bearer <token>
Request Body:
{
  "skills": ["JavaScript", "React", "Customer Support", "Database Management"]
}Response:
{
  "message": "Profile updated successfully",
  "user": {
    "_id": "user_id",
    "email": "user@example.com", 
    "role": "moderator",
    "skills": ["JavaScript", "React", "Customer Support", "Database Management"],
    "updatedAt": "2024-01-01T00:00:00.000Z"
  }
}Status Codes:
- 200- Profile updated successfully
- 400- Invalid skills format (must be array)
- 401- Unauthorized (token required)
- 500- Server error
Notes:
- Only authenticated users can update their own profile
- Skills array will completely replace existing skills
- Empty array is allowed to remove all skills
- Moderators can use this for self-service skills management
Get all users (Admin only).
Headers:
Authorization: Bearer <admin_token>
Response:
{
  "users": [
    {
      "_id": "user_id",
      "email": "user@example.com",
      "role": "user",
      "skills": ["JavaScript", "React"],
      "createdAt": "2024-01-01T00:00:00.000Z"
    }
  ]
}Status Codes:
- 200- Success
- 401- Unauthorized
- 403- Forbidden (non-admin)
Update user role and skills (Admin only).
Headers:
Authorization: Bearer <admin_token>
Request Body:
{
  "email": "user@example.com",
  "role": "moderator",
  "skills": ["JavaScript", "React", "Node.js"]
}Response:
{
  "message": "User updated successfully",
  "user": {
    "_id": "user_id",
    "email": "user@example.com",
    "role": "moderator",
    "skills": ["JavaScript", "React", "Node.js"]
  }
}Status Codes:
- 200- User updated successfully
- 401- Unauthorized
- 403- Forbidden (non-admin)
- 404- User not found
Get all tickets for the authenticated user.
Headers:
Authorization: Bearer <token>
Response:
[
  {
    "_id": "ticket_id",
    "title": "Login issue",
    "description": "Cannot login to the application",
    "status": "open",
    "priority": "high",
    "createdBy": {
      "_id": "user_id",
      "email": "user@example.com"
    },
    "assignedTo": null,
    "helpfulNotes": "AI analysis of the issue...",
    "replyCanbeGiven": [
      "Have you tried clearing your browser cache?",
      "Please check if your account is locked."
    ],
    "relatedSkills": ["Authentication", "Frontend"],
    "replies": [],
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-01T00:00:00.000Z"
  }
]Status Codes:
- 200- Success
- 401- Unauthorized
Create a new ticket.
Headers:
Authorization: Bearer <token>
Request Body:
{
  "title": "Login issue",
  "description": "I cannot login to the application. Getting error message."
}Response:
{
  "_id": "ticket_id",
  "title": "Login issue",
  "description": "I cannot login to the application. Getting error message.",
  "status": "open",
  "createdBy": "user_id",
  "helpfulNotes": "AI-generated analysis...",
  "replyCanbeGiven": ["Suggested reply 1", "Suggested reply 2"],
  "relatedSkills": ["Authentication"],
  "createdAt": "2024-01-01T00:00:00.000Z"
}Status Codes:
- 201- Ticket created successfully
- 400- Invalid input data
- 401- Unauthorized
Get a specific ticket by ID.
Headers:
Authorization: Bearer <token>
Response:
{
  "ticket": {
    "_id": "ticket_id",
    "title": "Login issue",
    "description": "Cannot login to the application",
    "status": "open",
    "createdBy": {
      "_id": "user_id",
      "email": "user@example.com"
    },
    "assignedTo": {
      "_id": "moderator_id",
      "email": "mod@example.com",
      "role": "moderator"
    },
    "helpfulNotes": "AI analysis...",
    "replyCanbeGiven": ["Suggested replies..."],
    "replies": [
      {
        "message": "We're looking into this issue.",
        "author": {
          "_id": "moderator_id",
          "email": "mod@example.com",
          "role": "moderator"
        },
        "createdAt": "2024-01-01T01:00:00.000Z"
      }
    ],
    "createdAt": "2024-01-01T00:00:00.000Z"
  }
}Status Codes:
- 200- Success
- 401- Unauthorized
- 403- Forbidden (not authorized to view)
- 404- Ticket not found
Update ticket assignment (Moderators/Admins only).
Headers:
Authorization: Bearer <moderator_token>
Request Body:
{
  "assignedTo": "moderator_user_id"
}Response:
{
  "message": "Ticket updated successfully",
  "ticket": {
    "_id": "ticket_id",
    "assignedTo": "moderator_user_id",
    "assignedAt": "2024-01-01T02:00:00.000Z"
  }
}Status Codes:
- 200- Ticket updated successfully
- 401- Unauthorized
- 403- Forbidden (not a moderator/admin)
- 404- Ticket not found
Add a reply to a ticket.
Headers:
Authorization: Bearer <token>
Request Body:
{
  "message": "Thank you for the help! The issue is resolved.",
  "status": "resolved" // Optional: Update ticket status
}Response:
{
  "message": "Reply added successfully",
  "reply": {
    "message": "Thank you for the help! The issue is resolved.",
    "author": "user_id",
    "createdAt": "2024-01-01T03:00:00.000Z"
  },
  "ticket": {
    "_id": "ticket_id",
    "status": "resolved" // If status was updated
  }
}Status Codes:
- 201- Reply added successfully
- 400- Invalid input data
- 401- Unauthorized
- 403- Forbidden (not authorized to reply)
- 404- Ticket not found
Update ticket status (Moderators/Admins only).
Headers:
Authorization: Bearer <moderator_token>
Request Body:
{
  "status": "resolved"
}Response:
{
  "message": "Ticket status updated successfully",
  "ticket": {
    "_id": "ticket_id",
    "status": "resolved",
    "resolvedAt": "2024-01-01T04:00:00.000Z"
  }
}Status Codes:
- 200- Status updated successfully
- 401- Unauthorized
- 403- Forbidden (not a moderator/admin)
- 404- Ticket not found
All error responses follow this format:
{
  "error": "Error message",
  "message": "Detailed error description"
}- 200- OK
- 201- Created
- 400- Bad Request
- 401- Unauthorized
- 403- Forbidden
- 404- Not Found
- 409- Conflict
- 500- Internal Server Error
Frontend expects these environment variables:
- VITE_SERVER_URL- Backend API URL
- VITE_API_URL- Alternative API URL
The system includes AI-powered features:
- AI Analysis (helpfulNotes): Automatically generated insights about the ticket
- AI Suggested Replies (replyCanbeGiven): Pre-written response suggestions for moderators
- Skill Detection (relatedSkills): Automatically detected skills related to the ticket
These AI features are populated when creating tickets and help moderators provide better support.
- All dates are in ISO 8601 format
- User roles: user(default),moderator,admin
- Ticket statuses: TODO,open,in-progress,resolved,closed,cancelled
- The frontend uses React with Tailwind CSS and DaisyUI
- Authentication uses JWT tokens
- Storage uses safe localStorage with fallbacks
- Check browser console for JavaScript errors
- Verify API URL in environment variables (should point to backend)
- Ensure backend server is running and accessible
- Clear browser cache and cookies to remove stale data
- Check network tab for failed API requests
Access to fetch at '...' has been blocked by CORS policy
Solutions:
- Verify CLIENT_URLenvironment variable is set correctly on backend
- Check if backend server is awake (Render free tier sleeps after 15 minutes)
- Test backend health endpoint: https://ticketmate-ai.onrender.com/health
- Ensure frontend domain is in CORS origins list
- Check network tab for failed requests (401, 500 errors)
- Verify backend deployment status in Render dashboard
- Test with development environment first (localhost:4000)
- Check if MongoDB is connected via health endpoint
- Validate JWT secret is set in production environment
- Skills not saving: Check browser console for API errors
- Profile page not loading: Verify user is authenticated and has valid token
- Skills not appearing: Check if API response includes skills array
- Server sleeping: Visit health endpoint to wake up server
- Deployment failed: Check Render logs for build/runtime errors
- Database connection: Verify MONGO_URLenvironment variable
- Environment variables missing: Ensure all required vars are set in Render
- Use npm run dev -- --hostto test frontend on mobile devices
- Backend logs are available in Render dashboard under "Logs" tab
- Frontend build logs available in Netlify deployment section
- Use browser dev tools Network tab to debug API calls
- Test API endpoints directly with tools like Postman or curl
- Frontend bundle analysis: Run npm run buildand check dist folder size
- API response times: Monitor slow endpoints in production
- Database queries: Use MongoDB indexes for frequently queried fields
- Image optimization: Compress and serve images in modern formats
- JWT tokens stored securely in localStorage with fallback handling
- Password hashing with bcrypt (salt rounds: 12)
- Role-based access control (RBAC) for API endpoints
- Protected routes prevent unauthorized access
- Input validation and sanitization on all endpoints
- CORS configuration prevents unauthorized cross-origin requests
- Environment variables for sensitive configuration
- MongoDB connection with authentication enabled
- All environment variables set securely
- CORS origins restricted to known domains
- JWT secret is strong and unique
- Database connection uses authentication
- HTTPS enabled for all production traffic
- Error messages don't expose sensitive information
- MongoDB connection pooling for efficient database access
- JWT token validation caching
- CORS preflight optimization
- Request retry logic with exponential backoff (frontend)
- API response compression
- Vite hot module replacement (HMR) for fast development
- Code splitting and tree shaking for optimized bundles
- Lazy loading of non-critical components
- Responsive images and modern image formats
- Tailwind CSS purging for minimal CSS bundle size
- Backend health endpoint for uptime monitoring
- Error logging and performance tracking
- User activity and engagement metrics
- API response time monitoring
- Database query performance analysis