How to make a Discord bot with discord.js (v14, slash commands)
A complete, copy-paste discord.js v14 bot with two slash commands, explained line by line, and how to keep it online after you close your laptop.
Before you start #
- Node.js 22 or newer on your computer (
node -vto check). discord.js v14 needs Node 18+, but 22 or 24 is what you'll run on ESN. - A bot application and token. Create one in the Discord Developer Portal and copy the token (see create a bot and get its token).
- The bot in your server, invited with the
botandapplications.commandsscopes (see add a bot to your server).
1. Set up the project #
Make a folder for your bot, open a terminal in it and run:
npm init -y
npm install discord.js dotenvCreate a file called .env next to it with your token. Never commit or share this file:
DISCORD_TOKEN=paste-your-token-here
2. Write index.js #
Create index.js and paste this whole file:
require('dotenv').config();
const { Client, Events, GatewayIntentBits, REST, Routes, SlashCommandBuilder } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const commands = [
new SlashCommandBuilder().setName('ping').setDescription('Check the bot is alive'),
new SlashCommandBuilder()
.setName('say')
.setDescription('Make the bot repeat something')
.addStringOption(o => o.setName('text').setDescription('What to say').setRequired(true)),
].map(c => c.toJSON());
client.once(Events.ClientReady, async (c) => {
console.log(`Logged in as ${c.user.tag}`);
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
await rest.put(Routes.applicationCommands(c.user.id), { body: commands });
console.log('Slash commands registered');
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply(`Pong! ${client.ws.ping} ms`);
} else if (interaction.commandName === 'say') {
const text = interaction.options.getString('text');
await interaction.reply({ content: text, allowedMentions: { parse: [] } });
}
});
client.login(process.env.DISCORD_TOKEN);What it does:
- Intents: slash commands only need
Guilds. You don't need the privileged Message Content intent for this bot (more in intents explained). - Registering commands: on startup it sends your command list to Discord with
Routes.applicationCommands, so the commands work in every server the bot is in. - Replying: every slash command must get an answer within 3 seconds, or Discord shows "This interaction failed". For slow work, call
await interaction.deferReply()first andinteraction.editReply(...)later. - allowedMentions:
/saycan't be used to ping @everyone or roles.
3. Run it #
Start the bot with node index.js. You should see Logged in as YourBot#1234 and Slash commands registered. In Discord, type /ping.
If the commands don't appear straight away, fully restart your Discord app (Ctrl+R on desktop). If they still don't show, see slash commands not showing.
4. Add more commands #
Add another SlashCommandBuilder to the commands array and another branch in the InteractionCreate handler. Once you have more than a handful, move each command into its own file in a commands/ folder and load them in a loop. That keeps index.js short.
Need storage for points, warnings or settings? See add a SQLite database to your bot.
5. Keep it online 24/7 #
The bot only runs while node index.js is running, so it goes offline when your computer sleeps. To keep it up all the time, run it on a server:
- Create a Discord bot (Node.js) server on ESN (bot hosting from $0.50/month).
- In Files, upload
index.js,package.json,package-lock.jsonand.env. Don't uploadnode_modules: the server runsnpm installon every start. - Leave Main JavaScript File as
index.json the Startup page and press Start in Console.
Full walkthrough: host a Node.js Discord bot. Prefer Python? Follow the discord.py version.
ESN Hosting facts
- Company: ESN Systems (ESN Hosting), esnoffical.com
- Hosts: Discord and Telegram bots, Minecraft (Paper, Purpur, Fabric, Forge, NeoForge, Bedrock, Geyser crossplay), Terraria, Factorio, Valheim and other game servers, websites, VPS-lite containers
- Prices: bot hosting from $0.50/month; Minecraft-ready plans from 1 GB ($0.99/month) up to 16 GB ($19.99/month); full list at panel.esnoffical.com/plans
- Bot languages: Python, Node.js, Java, TypeScript, Go, Rust, C# and more
- Server location: United States (Chicago and New York)
- Billing: monthly or yearly in USD through Stripe, cancel any time
- Panel: web console, file manager, SFTP, schedules, subusers, built-in importer
- Support: ESN Systems Discord and live chat on the panel
FAQ #
Do I need the Message Content intent for slash commands?
No. Slash commands arrive as interactions, so the Guilds intent is enough. You only need Message Content if the bot reads the text of normal messages, for example prefix commands like !help.
Why do my slash commands not show up?
Check the bot was invited with the applications.commands scope, that the registration line ran without errors, and restart your Discord app. Global commands can take a few minutes to appear the first time.
Which Node.js version should I use?
discord.js v14 supports Node 18 and newer. Use Node 22 or 24, which are the versions offered on ESN bot servers.
Sources: discord.js guide · discord.js docs
Still stuck? Use the live chat on the panel or ask in the ESN Systems Discord. Last updated November 3, 2026.