A Discord bot providing a complete ticketing system for customer support and help desk operations. Built with Discord.js v14 and Supabase PostgreSQL for enterprise-grade reliability, multi-server support, and persistent data storage.
- Features
- Prerequisites
- Installation
- Discord Bot Configuration
- Supabase Database Setup
- Environment Variables
- Running the Bot
- Commands
- Usage Guide
- Deployment
- Project Structure
- Database Schema
- Troubleshooting
- Security
- Contributing
- License
- Support
- Modern slash commands with Discord.js v14
- Persistent PostgreSQL database storage via Supabase
- Multi-server support with isolated configurations
- Automatic ticket transcripts with full message history
- Role-based staff access control
- Ticket claiming system for staff management
- Customizable embed colors and styling
- Real-time bot activity status updates
- Health check endpoint for uptime monitoring
- Automatic command deployment on startup
- Comprehensive error handling and retry logic
- Docker support for containerized deployment
- Production-ready with colorful console logging
Before installing SupportHub, ensure you have:
- Node.js 20.0.0 or higher - Download here
- npm (comes with Node.js) or pnpm
- Discord Account - Sign up here
- Supabase Account - Sign up for free
- Git - Download here
git clone https://github.com/nayandas69/supporthub.git
cd supporthubUsing npm:
npm installUsing pnpm:
pnpm installCopy the example environment file:
cp .env.example .envEdit the .env file with your credentials (see Environment Variables section).
Follow these steps carefully to create and configure your Discord bot application.
- Navigate to the Discord Developer Portal
- Click "New Application" in the top-right corner
- Enter a name for your application (e.g., "SupportHub")
- Read and accept the Discord Developer Terms of Service
- Click "Create"
- In your application page, click "Bot" in the left sidebar
- Click "Add Bot" and confirm by clicking "Yes, do it!"
- Under the bot's username section, click "Reset Token"
- Click "Yes, do it!" to confirm
- Copy the token immediately - this is your
DISCORD_TOKEN- This token will only be shown once
- Store it securely in your
.envfile - Never share this token publicly or commit it to version control
Scroll down to the "Privileged Gateway Intents" section and enable:
- SERVER MEMBERS INTENT - Required for role and member management
- MESSAGE CONTENT INTENT - Required for reading ticket messages
Click "Save Changes" at the bottom.
- Click "OAuth2" in the left sidebar
- Select "General" from the submenu
- Under "Client Information", copy the Client ID
- This is your
CLIENT_ID- save it in your.envfile
When configuring your Discord bot application, you MUST set the correct installation contexts:
- In the Discord Developer Portal, navigate to your application
- Click "Installation" in the left sidebar
- Under "Installation Contexts", you will see two options:
- Guild Install - Allows installation to Discord servers
- User Install - Allows installation to user accounts
IMPORTANT: Select ONLY "Guild Install"
- CHECK: Guild Install
- UNCHECK: User Install
Why Guild Install Only?
- SupportHub is designed to work exclusively within Discord servers (guilds)
- The bot requires server-specific permissions, roles, categories, and channels
- User Install would not provide the necessary server context for ticket management
- Ticket systems are server-wide features, not user-specific features
Do NOT enable User Install - the bot will not function correctly if installed to user accounts.
- Still in the "Installation" section
- Under "Default Install Settings" for Guild Install
- Set "Scopes":
botapplications.commands
- Set "Permissions" (required for ticket system):
- View Channels
- Send Messages
- Embed Links
- Attach Files
- Read Message History
- Add Reactions
- Use External Emojis
- Manage Channels
- Manage Roles
- Manage Messages
Alternatively, you can use permission integer: 8 (Administrator) for testing, but this is not recommended for production.
- Go to "OAuth2" in the left sidebar
- Select "URL Generator"
- Under "Scopes", check:
botapplications.commands
- Under "Bot Permissions", select the permissions listed above
- Copy the generated URL at the bottom
- Open the URL in your browser
- Select your Discord server from the dropdown
- Click "Authorize"
- Complete the CAPTCHA if prompted
Your bot should now appear offline in your server's member list.
SupportHub uses Supabase (PostgreSQL) for persistent data storage. Follow these steps to set up your database.
- Visit Supabase Dashboard
- Sign in or create a new account
- Click "New Project"
- Select or create an organization
- Configure your project:
- Name:
supporthub(or your preferred name) - Database Password: Create a strong password (save this securely)
- Region: Choose the region closest to your users for best performance
- Pricing Plan: Free tier is sufficient for most use cases
- Name:
- Click "Create new project"
- Wait 2-3 minutes for Supabase to provision your database
Once your project is ready:
- Click on "Settings" (gear icon) in the left sidebar
- Select "API" from the settings menu
- Find your credentials:
Project URL:
- Look for the "Project URL" section
- Copy the URL (format:
https://abcdefghijklmnop.supabase.co) - This is your
SUPABASE_URL
Service Role Key:
- Scroll to "Project API keys" section
- Find the
service_rolekey (NOT theanonkey) - Click the eye icon to reveal the key
- Copy the entire key
- This is your
SUPABASE_SERVICE_ROLE_KEY
IMPORTANT:
- The service role key bypasses Row Level Security
- NEVER expose this key in client-side code
- Keep it secure in your
.envfile - Do not commit it to version control
- In Supabase Dashboard, click "SQL Editor" in the left sidebar
- Click "New Query" button
Run First Script:
- Open the file
db/init_supporthub_database.sqlfrom your project directory - Copy the entire contents
- Paste into the SQL Editor in Supabase
- Click "Run" or press
Ctrl+Enter(Windows/Linux) orCmd+Enter(Mac) - You should see "Success. No rows returned" message
- Verify tables were created by clicking "Table Editor" in the sidebar
- You should see:
guild_configs,tickets,ticket_messages
- You should see:
Run Second Script:
- Click "New Query" again in SQL Editor
- Open the file
db/setup_security_policies.sqlfrom your project - Copy the entire contents
- Paste into the SQL Editor
- Click "Run"
- Verify Row Level Security is enabled
Your database is now fully configured and ready to use.
To confirm everything is set up correctly:
- Go to "Table Editor" in Supabase
- You should see three tables:
guild_configs- Stores server ticket configurationstickets- Stores individual ticket dataticket_messages- Stores ticket message history
- Click on each table to verify the schema matches the SQL scripts
Create a .env file in the project root directory with the following variables:
# ============================================
# Discord Bot Configuration
# ============================================
# Your Discord bot token from the Developer Portal
# Located in: Bot section > Token
DISCORD_TOKEN=your_discord_bot_token_here
# Your Discord application client ID
# Located in: OAuth2 > General > Client ID
CLIENT_ID=your_discord_client_id_here
# ============================================
# Supabase Database Configuration
# ============================================
# Your Supabase project URL
# Located in: Settings > API > Project URL
# Format: https://abcdefghijklmnop.supabase.co
SUPABASE_URL=https://your-project-id.supabase.co
# Your Supabase service role key (NOT the anon key)
# Located in: Settings > API > service_role key
# IMPORTANT: Keep this secret - it has full database access
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here
# ============================================
# Optional Configuration
# ============================================
# Application environment (development or production)
NODE_ENV=production
# Health check HTTP server port
# Used by uptime monitors to verify bot is running
# Default: 3000
PORT=3000
# Alternative health check port variable name
HEALTH_CHECK_PORT=3000Run with auto-restart on file changes (using Node.js built-in watch mode):
npm run devThis is useful during development as the bot will automatically restart when you modify any source files.
Run the bot normally:
npm startWhen the bot starts successfully, you should see:
[SYSTEM] Starting SupportHub Bot...
[INFO] Node.js version: v20.11.0
[SYSTEM] Connecting to Supabase database...
[SUCCESS] Supabase connection established successfully
[INFO] Loading 3 command files...
[SUCCESS] Loaded command: setup
[SUCCESS] Loaded command: reconfigure
[SUCCESS] Loaded command: remove-setup
[SUCCESS] Successfully loaded 3 commands
[INFO] Loading 2 event files...
[SUCCESS] Loaded event: ready
[SUCCESS] Loaded event: interactionCreate
[SUCCESS] Successfully loaded 2 events
[SUCCESS] Logged in as SupportHub#1234
[SYSTEM] Deploying slash commands to Discord API...
[SUCCESS] Successfully deployed 3 slash commands globally
[SUCCESS] Health check server running on port 3000
If you see these messages, your bot is running correctly!
For production environments, use PM2 for process management:
# Install PM2 globally
npm install -g pm2
# Start bot with PM2
pm2 start src/index.js --name supporthub
# View logs
pm2 logs supporthub
# Monitor bot status
pm2 status
# Restart bot
pm2 restart supporthub
# Stop bot
pm2 stop supporthub
# Remove from PM2
pm2 delete supporthub
# Save PM2 configuration
pm2 save
# Setup PM2 to start on system boot
pm2 startupSupportHub provides three slash commands for server owners to manage the ticket system.
Description: Initial configuration of the ticket system for your server.
Permission Required: Server Owner only
Options:
panel-channel(required) - Text channel where the ticket creation panel will be postedcategory(required) - Category where individual ticket channels will be createdstaff-role(required) - Role that can view and manage ticketstranscript-channel(optional) - Channel where ticket transcripts will be savedembed-color(optional) - Hex color code for embeds (default: #5865F2)
Example:
/setup
panel-channel: #support
category: Support Tickets
staff-role: @Support Team
transcript-channel: #ticket-logs
embed-color: #5865F2
Description: Modify existing ticket system configuration.
Permission Required: Server Owner only
Options:
- Same options as
/setup - Updates existing configuration without deleting tickets
- Panel message is automatically updated
Example:
/reconfigure
staff-role: @New Support Team
transcript-channel: #new-logs
Description: Completely remove the ticket system from your server.
Permission Required: Server Owner only
Warning: This action:
- Deletes all active ticket channels immediately
- Removes the ticket panel message
- Deletes configuration from the database
- Cannot be undone
Example:
/remove-setup
- Ensure bot is invited to your server with correct permissions
- Create a category for tickets (e.g., "Support Tickets")
- Create a text channel for the panel (e.g., "#support")
- Create or identify a staff role (e.g., "@Support Team")
- Create a channel for logs (e.g., "#ticket-logs")
- Run the
/setupcommand with your configuration - The ticket panel will appear in your chosen channel
- Navigate to the support channel
- Find the ticket panel embed
- Click the "Create Ticket" button
- A private channel is created instantly (e.g.,
#ticket-1234) - Only you, staff members, and server admins can see this channel
- Describe your issue or question
- Wait for a staff member to respond
Note: You can only have one active ticket at a time.
Claim a Ticket:
- Click the "Claim Ticket" button in the ticket channel
- Your name will be recorded as the handler
- Other staff will see the ticket is being handled
Close a Ticket:
- Click the "Close Ticket" button when the issue is resolved
- A full transcript is automatically generated
- The transcript is sent to the logs channel
- The ticket channel is deleted after 5 seconds
- The ticket is marked as closed in the database
Transcript Format:
- Ticket number and ID
- User who created the ticket
- Staff member who claimed the ticket
- Creation and closure timestamps
- Full message history in readable format
- Copyable text for record keeping
Railway provides free hosting with automatic deployments from Git.
- Create an account at Railway.app
- Click "New Project"
- Select "Deploy from GitHub repo"
- Authorize Railway to access your GitHub account
- Select your SupportHub repository (fork it first if needed)
- Railway will automatically detect the Node.js project
- Add environment variables:
- Go to project settings
- Click "Variables" tab
- Add each variable from your
.envfile DISCORD_TOKENCLIENT_IDSUPABASE_URLSUPABASE_SERVICE_ROLE_KEYNODE_ENV=production
- Railway will automatically build and deploy your bot
- Copy your Railway deployment URL for health checks
Railway Features:
- Free $5 monthly credit (sufficient for small bots)
- Automatic deployments on git push
- Built-in PostgreSQL if you don't want to use Supabase
- Easy environment variable management
- Automatic HTTPS and domain assignment
Render provides free hosting for web services.
- Create an account at Render.com
- Click "New" β "Web Service"
- Connect your GitHub or GitLab account
- Select your SupportHub repository
- Configure the service:
- Name:
supporthub - Environment:
Node - Build Command:
npm install - Start Command:
npm start - Plan: Free
- Name:
- Add environment variables in the dashboard
- Click "Create Web Service"
- Wait for the initial deployment to complete
Render Features:
- Free tier with 750 hours/month
- Automatic SSL certificates
- Automatic deploys from Git
- Built-in health checks
- Custom domains supported
Build and run the bot using Docker containers.
Using Docker directly:
# Build the Docker image
docker build -t supporthub:latest .
# Run the container
docker run -d \
--name supporthub \
--restart unless-stopped \
--env-file .env \
-p 3000:3000 \
supporthub:latest
# View logs
docker logs -f supporthub
# Stop container
docker stop supporthub
# Remove container
docker rm supporthubUsing Docker Compose:
# Start in detached mode
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Rebuild and restart
docker-compose up -d --buildManual deployment on your own Virtual Private Server.
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Verify installation
node --version # Should show v20.x.x
npm --version
# Install Git (if not installed)
sudo apt install git -y
# Clone the repository
git clone https://github.com/nayandas69/supporthub.git
cd supporthub
# Install dependencies
npm install
# Configure environment
nano .env # Add your credentials
# Install PM2 for process management
sudo npm install -g pm2
# Start the bot
pm2 start src/index.js --name supporthub
# View logs
pm2 logs supporthub
# Save PM2 configuration
pm2 save
# Setup PM2 to start on system boot
pm2 startup
# Follow the instructions shown (usually requires running a command with sudo)
# Monitor bot status
pm2 monitsupporthub/
βββ src/
β βββ index.js # Bot entry point and initialization
β βββ commands/
β β βββ setup.js # /setup command - initial configuration
β β βββ reconfigure.js # /reconfigure command - update settings
β β βββ remove-setup.js # /remove-setup command - remove system
β βββ events/
β β βββ ready.js # Bot ready event handler
β β βββ interactionCreate.js # Slash commands and button interactions
β βββ handlers/
β β βββ ticketHandler.js # Core ticket creation/management logic
β βββ utils/
β β βββ log.js # Colorful console logging utility
β β βββ supabase.js # Supabase client and connection pooling
β β βββ storage-supabase.js # Database CRUD operations
β β βββ activityManager.js # Dynamic bot activity status
β β βββ healthcheck.js # HTTP health check server
β βββ config/
β βββ config.js # Environment variable configuration
βββ db/
β βββ init_supporthub_database.sql # Database table creation script
β βββ setup_security_policies.sql # Row Level Security setup
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ package.json # Node.js dependencies and scripts
βββ package-lock.json # Locked dependency versions
βββ Dockerfile # Docker container configuration
βββ docker-compose.yml # Docker Compose orchestration
βββ railway.json # Railway deployment configuration
βββ README.md # This documentation file
Stores per-server ticket system configuration.
| Column | Type | Description |
|---|---|---|
guild_id |
TEXT | Discord server ID (Primary Key) |
panel_channel_id |
TEXT | Channel ID where ticket panel is posted |
panel_message_id |
TEXT | Message ID of the ticket panel |
category_id |
TEXT | Category ID where tickets are created |
staff_role_ids |
TEXT[] | Array of staff role IDs |
transcript_channel_id |
TEXT | Channel ID for ticket transcripts (nullable) |
embed_color |
TEXT | Hex color code for embeds (default: #5865F2) |
enabled |
BOOLEAN | Whether ticket system is active |
created_at |
TIMESTAMPTZ | Configuration creation timestamp |
last_updated |
TIMESTAMPTZ | Last update timestamp |
Stores information about all created tickets.
| Column | Type | Description |
|---|---|---|
id |
TEXT | Ticket ID (format: ticket-{userId}-{timestamp}) Primary Key |
ticket_number |
INTEGER | 4-digit display number (e.g., 1234) |
guild_id |
TEXT | Discord server ID |
channel_id |
TEXT | Ticket channel ID |
user_id |
TEXT | User ID who created the ticket |
claimed_by |
TEXT | Staff user ID who claimed (nullable) |
status |
TEXT | Ticket status: open, claimed, or closed |
created_at |
TIMESTAMPTZ | Ticket creation timestamp |
closed_at |
TIMESTAMPTZ | Ticket closure timestamp (nullable) |
Stores message history for ticket transcripts (optional logging).
| Column | Type | Description |
|---|---|---|
id |
BIGSERIAL | Auto-incrementing message ID (Primary Key) |
ticket_id |
TEXT | References tickets.id |
message_id |
TEXT | Discord message ID |
user_id |
TEXT | User who sent the message |
username |
TEXT | Username at time of message |
content |
TEXT | Message content |
created_at |
TIMESTAMPTZ | Message timestamp |
Optimized indexes for common queries:
idx_guild_configs_enabled- Active guild configurationsidx_tickets_guild_id- Tickets by serveridx_tickets_user_id- Tickets by useridx_tickets_status- Tickets by statusidx_tickets_channel_id- Tickets by channelidx_tickets_user_active- Active tickets by user in a serveridx_ticket_messages_ticket_id- Messages by ticket
Symptoms: Slash commands don't appear in the command menu or don't execute.
Solutions:
-
Verify Bot Invite Scopes:
- Ensure bot was invited with both
botandapplications.commandsscopes - Re-generate invite link and re-invite if needed
- Ensure bot was invited with both
-
Check Bot Permissions:
- Bot needs Administrator permission or all required permissions listed above
- Verify bot role is not below restricted roles in server settings
-
Wait for Command Sync:
- Discord can take up to 1 hour to sync global commands
- Restart your Discord client (Ctrl+R or Cmd+R)
- Try in incognito/private browsing mode
-
Verify Bot is Online:
- Check bot shows as online in server member list
- Review console logs for connection errors
-
Check Console for Errors:
- Look for "Failed to deploy commands" errors
- Verify
CLIENT_IDmatches your application ID
Symptoms: "Failed to connect to Supabase" or "Database operation failed" errors.
Solutions:
-
Verify Credentials:
- Double-check
SUPABASE_URLhas no trailing slash - Ensure you're using
service_rolekey, NOTanonkey - Check for extra spaces or quotes in
.envfile
- Double-check
-
Check Supabase Project Status:
- Free tier projects may pause after inactivity
- Visit Supabase dashboard to wake the project
- Set up uptime monitoring to prevent pausing
-
Verify Database Schema:
- Run both SQL scripts in correct order
- Check Table Editor to confirm tables exist
- Verify Row Level Security is configured
-
Network Issues:
- Check firewall allows connections to Supabase
- Verify your IP is not blocked in Supabase settings
- Test connection using Supabase SQL Editor
-
Connection Pooling:
- If seeing "too many connections" errors
- Restart the bot to reset connection pool
- Check if multiple bot instances are running
Symptoms: "Missing permissions" or "Failed to create ticket channel" errors.
Solutions:
-
Check Role Hierarchy:
- Bot's role must be ABOVE the ticket category in role hierarchy
- Go to Server Settings > Roles
- Drag bot role above all staff roles
-
Verify Category Permissions:
- Bot needs these permissions in the category:
- View Channels
- Manage Channels
- Manage Roles
- Send Messages
- Embed Links
- Bot needs these permissions in the category:
-
Check Category Limit:
- Discord categories have a 50 channel maximum
- Create a new category if limit is reached
- Run
/reconfigureto switch categories
-
Verify Category Exists:
- Ensure the category wasn't deleted
- Run
/reconfigureto select a new category if needed
Symptoms: Users click button but nothing happens.
Solutions:
-
Check User Has Only One Ticket:
- Users can only have one active ticket at a time
- Close existing ticket before creating a new one
- Check for orphaned ticket channels
-
Verify Bot Can See Category:
- Bot must have View Channels permission
- Check category permissions explicitly allow the bot
-
Review Console Logs:
- Look for specific error messages
- Errors will indicate exact permission or configuration issues
-
Panel Message Deleted:
- If panel message was deleted, run
/reconfigure - Panel will be recreated automatically
- If panel message was deleted, run
Symptoms: Uptime monitor shows bot as down, 503 errors.
Solutions:
-
Check Bot Process:
- Verify bot is actually running:
pm2 status - Check for crash errors:
pm2 logs supporthub --err
- Verify bot is actually running:
-
Port Configuration:
- Verify
PORTenvironment variable is set correctly - Check firewall allows traffic on the port
- Ensure port is not already in use
- Verify
-
Test Locally:
curl http://localhost:3000/health
- Should return JSON with bot status
- If timeout, health check server didn't start
-
Deployment Platform:
- Railway/Render may assign a different port
- Check platform documentation for PORT variable
- Some platforms require binding to
0.0.0.0
Symptoms: Closed tickets don't generate transcripts.
Solutions:
-
Check Transcript Channel:
- Verify transcript channel still exists
- Ensure bot has Send Messages and Embed Links permissions
- Run
/reconfigureto set a new transcript channel
-
Verify Database Write:
- Check console for database write errors
- Confirm Supabase connection is active
-
Message History Permissions:
- Bot needs Read Message History permission
- Without it, bot cannot fetch messages for transcript
-
Environment Variables:
- Use different credentials for development and production
- Rotate tokens if exposed
-
Discord Token Security:
- Treat bot token like a password
- If leaked, reset immediately in Developer Portal
- Monitor bot activity for unauthorized usage
-
Supabase Security:
- Use service role key only in backend code
- Never expose service key in client-side code
- Enable Row Level Security on all tables
- Regularly review Supabase API logs
-
Bot Permissions:
- Grant only required permissions
- Avoid using Administrator permission in production
- Regularly audit bot's server access
-
Server Security:
- Keep Node.js and dependencies updated
- Use
npm auditto check for vulnerabilities - Run bot with limited system user (not root)
- Configure firewall to allow only necessary ports
-
Database Security:
- Regularly backup Supabase database
- Monitor database queries for unusual activity
- Use parameterized queries (already implemented)
- Enable audit logging in Supabase
If you discover a security vulnerability, please email: nayanchandradas@hotmail.com
Do not open public GitHub issues for security vulnerabilities.
Contributions are welcome! Here's how you can help improve SupportHub.
- Check existing issues to avoid duplicates
- Open a new issue with:
- Clear description of the bug
- Steps to reproduce
- Expected vs actual behavior
- Console logs/error messages
- Node.js version and OS
- Open an issue with the "enhancement" label
- Describe the feature and use case
- Explain how it would benefit users
- Consider implementation complexity
- Fork the repository
- Create a new branch:
git checkout -b feature/your-feature-name - Make your changes following code style
- Test thoroughly
- Commit with clear messages
- Push to your fork
- Open a Pull Request with detailed description
- Follow existing code structure and style
- Add comments for complex logic
- Test with multiple Discord servers
- Verify database operations work correctly
- Update documentation for new features
This project is licensed under the MIT License - see the LICENSE file for details.
Need help? Have questions? Here are your options:
- Discord Community: Join our Discord
- GitHub Issues: Report bugs or request features
- Documentation: You're reading it!
- Email Support: nayanchandradas@hotmail.com
- Author: nayandas69
- Built with:
- Discord.js v14 - Discord API wrapper
- Supabase - PostgreSQL database hosting
- Node.js - JavaScript runtime
- Chalk - Terminal styling
- dotenv - Environment variable management
- Initial release
- Modern slash commands with Discord.js v14
- Supabase PostgreSQL integration
- Multi-server support
- Ticket claiming system
- Automatic transcripts
- Health check endpoint
- Docker support
- Comprehensive documentation
Made with dedication by nayandas69
Star this repository if you find it useful!