Node.js Guide
This guide walks you through deploying a Discord bot in Node.js on KataBump. We'll use the discord.js library, which is the most popular and complete.
Prerequisites
- Node.js installed on your machine (for development)
- A Discord bot created on the Developer Portal
- Your bot's token
Create Your Project
Recommended Structure
/my-discord-bot/
├── package.json
├── index.js
├── .env (local only)
└── commands/
└── ping.js1. Initialize the Project
mkdir my-discord-bot
cd my-discord-bot
npm init -y2. Install discord.js
npm install discord.js3. Create package.json
Make sure your package.json looks like this:
{
"name": "my-discord-bot",
"version": "1.0.0",
"description": "My Discord bot hosted on KataBump",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node index.js"
},
"dependencies": {
"discord.js": "^14.14.1"
},
"engines": {
"node": ">=18.0.0"
}
}"start" Script
The "start" script is required. This is the command KataBump uses to start your bot.
4. Create the Bot
Create an index.js file:
const { Client, GatewayIntentBits, Events } = require('discord.js');
// Create the Discord client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers
]
});
// "ready" event - when the bot is connected
client.once(Events.ClientReady, (readyClient) => {
console.log(`Connected as ${readyClient.user.tag}`);
console.log(`ID: ${readyClient.user.id}`);
});
// Respond to messages
client.on(Events.MessageCreate, (message) => {
// Ignore messages from the bot itself
if (message.author.bot) return;
// !ping command
if (message.content === '!ping') {
message.reply('Pong!');
}
// !hello command
if (message.content === '!hello') {
message.reply(`Hello ${message.author.username}!`);
}
});
// Connect with the environment token
const TOKEN = process.env.DISCORD_TOKEN;
if (!TOKEN) {
console.error('Error: DISCORD_TOKEN variable is not defined');
process.exit(1);
}
client.login(TOKEN).catch((error) => {
console.error('Connection error:', error);
process.exit(1);
});
// Error handling
process.on('unhandledRejection', (error) => {
console.error('Unhandled error:', error);
});5. Set Up Environment Variables
Create a .env file at the root of your project:
DISCORD_TOKEN=your_token_hereInstall dotenv as a dependency:
npm install dotenvAdd the following at the very top of index.js:
require('dotenv').config();.env on KataBump
The .env file is used both locally and on KataBump. Upload it to your server along with your other files. See Set Environment Variables for more details.
6. Test Locally (optional)
npm start::: success Works Locally? If your bot works locally, it will work on KataBump! :::
Deploy to KataBump
1. Create a Node.js Server
- Log in to dashboard.katabump.com
- Click "Create a server"
- Choose Node.js
- Name your server
- Click "Create"
- On control.katabump.com, go to the "Startup" tab to select your Node.js version (recommended: 18 or 20 LTS)
2. Upload Files
Via Web
- Create a ZIP file containing your project files
- Go to the "Files" tab on control.katabump.com
- Drag and drop your ZIP file
- Unzip the file on the panel
- Make sure
package.jsonandindex.jsare at the root
Via SFTP
- Retrieve your SFTP credentials in the "Settings" section
- Connect with FileZilla
- Upload files to
/home/container
3. Configure Startup
- Go to the "Startup" tab on control.katabump.com
- Set the "JS FILE" to your entry point (e.g.
index.js) - Save
Environment Variables
Your .env file (containing your DISCORD_TOKEN) should already be included in your uploaded files. If not, upload it via the file manager or SFTP.
4. Start the Server
- Go to the "Console" tab
- Click "Start"
- Wait for dependency installation (automatic npm install)
- You should see:
Connected as MyBot#1234 ID: 123456789
::: success Bot Online! Your bot is now connected 24/7! :::
Slash Commands
Slash commands are the new standard recommended by Discord.
Example with Slash Commands
const { Client, GatewayIntentBits, Events, SlashCommandBuilder } = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds]
});
// Commands to register
const commands = [
new SlashCommandBuilder()
.setName('ping')
.setDescription('Responds with Pong!'),
new SlashCommandBuilder()
.setName('info')
.setDescription('Displays information')
];
client.once(Events.ClientReady, async (readyClient) => {
console.log(`Connected as ${readyClient.user.tag}`);
// Register commands (do this only once)
try {
await readyClient.application.commands.set(commands);
console.log('Slash commands registered');
} catch (error) {
console.error('Registration error:', error);
}
});
// Handle interactions
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong!');
}
if (interaction.commandName === 'info') {
await interaction.reply({
content: `**Information**\n` +
`Server: ${interaction.guild.name}\n` +
`Members: ${interaction.guild.memberCount}`,
ephemeral: true // Message visible only to the user
});
}
});
client.login(process.env.DISCORD_TOKEN);Command Registration
Slash commands need to be registered once, then Discord caches them. Modify the code to register, start, then comment out the registration part.
Best Practices
Error Handling
// Always handle errors
client.on(Events.Error, (error) => {
console.error('Discord error:', error);
});
// Unhandled errors
process.on('unhandledRejection', (error) => {
console.error('Unhandled rejection:', error);
});
process.on('uncaughtException', (error) => {
console.error('Uncaught exception:', error);
process.exit(1);
});Using PM2 (optional)
For advanced process management, you can use PM2:
// package.json
{
"scripts": {
"start": "pm2-runtime start ecosystem.config.js"
},
"dependencies": {
"pm2": "^5.3.0"
}
}// ecosystem.config.js
module.exports = {
apps: [{
name: 'discord-bot',
script: './index.js',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '250M'
}]
};Memory Optimization
// package.json
{
"scripts": {
"start": "node --max-old-space-size=256 index.js"
}
}Free Plan Memory
The free plan provides 308 MB RAM. Set --max-old-space-size accordingly to avoid OOM errors.