/ping slash command: you register the command once, then start the bot and use it in your server. If this is your first bot, copy each block as you reach it.
Create a folder for your bot and set it up with
bun init. Pick the defaults when it asks.
terminal
Add Discord.js to the project.
terminal
Your bot needs its own account, which you create in Discord’s developer portal. Open the developer portal, sign in, and create an Application. Inside it, open the Bot tab to create the bot user. Discord’s setup walkthrough has screenshots if you get lost. Copy two values from the portal:
- The token on the Bot tab. It’s the password your code uses to log in, so treat it like one and keep it to yourself.
- The Application ID on the General Information tab. Discord uses it to tie your commands to this app.
A bot can’t do anything in a server until you invite it. In the portal’s OAuth2 section, generate an invite URL with the
bot and applications.commands scopes, open it, and add the bot to a server you manage. Slash commands need the applications.commands scope, so don’t skip it. A personal server you make for testing is the easiest place to start, and Discord’s guide to adding a bot walks through it with screenshots.
You also need your server’s ID to register the command there. In Discord, turn on Settings > Advanced > Developer Mode, then right-click your server’s icon and choose Copy Server ID.
Save all three values in
.env.local. Bun reads this file on startup and loads it into process.env, so nothing secret lives in your code.
.env.local
Add
.env.local to your .gitignore before you commit anything. Anyone who reads the token can control your bot, so it should never land in version control.
.gitignore
Discord has to know about a command before anyone can use it. Register
/ping with a short script named deploy-commands.ts.
terminal
Now the bot itself. Save it as
bot.ts.
interactionCreate runs whenever someone uses a slash command; it confirms the command was /ping and replies with Pong!.
Start the bot with
bun run.
terminal
/ping in your server.
Pong!. You’ve got a working Discord bot.
To add another command, define it in
deploy-commands.ts, run that script again, and add an if branch for its name in bot.ts. The Discord.js docs cover command options, permissions, buttons, embeds, and the rest of the API.
When you deploy, there’s no build or bundling step. Bun runs
bot.ts and every file it imports directly, so you ship your source as-is and start it with the same bun run bot.ts you use while developing.
deploy-commands.ts registers /ping in your test server, which is the right scope while you’re building. To publish the bot to every server it joins, register globally instead: change the route to Routes.applicationCommands(DISCORD_CLIENT_ID). Global registration doesn’t use a server, so you can also drop DISCORD_GUILD_ID from the script’s check and from .env.local.
To keep the bot online and bring it back after a crash or reboot, run it under a process manager.
systemd
Run your bot as a Linux daemon
PM2
Manage your bot with PM2