Deploy a Discord bot

A slash-command bot that stays online, on the free plan.

The discord-bot-starter template answers /ping and /roll (dice like 2d6+1) and is a short, plain starting point for your own commands. It runs always on, so it keeps answering when your laptop is closed.

1. Get a bot token from Discord

  1. Open the Discord developer portal and choose New Application.
  2. Open the Bot page and choose Reset Token. Copy it now, because Discord shows it once.
  3. Leave the Privileged Gateway Intents switches off. This bot does not read messages, so it needs none of them.
  4. Optional: switch off Public Bot on the same page, so only you can add the bot to a server.

Open the deploy link and sign in if asked. Under App size, keep 256 MB. The free plan is enough.

3. Add the token

Under Environment, in the Secrets list, click New secret and set its Env var name to DISCORD_TOKEN. Give the entry a name that belongs to this app, for example discord-bot-token, because secrets are shared across your apps by name. Paste the token as the value, then click Deploy.

Secret (your name)Env var nameValue
discord-bot-tokenDISCORD_TOKENThe token from the Bot page

Deployed without the token? Create it under Secrets in the dashboard sidebar and attach it on the app's Variables tab as DISCORD_TOKEN. The app restarts and picks it up.

4. Invite the bot

Open the app's URL. The page is a short JSON status. Once the bot is connected it shows "gateway": "connected" and an invite link. Copy that link into your browser and pick your server. It asks for the bot and applications.commands scopes and no extra permissions, since slash command replies need none. Then type /ping in your server.

The status page tells you what is wrong. gateway is connected, connecting or no token, and message says what to fix. A missing token and a token Discord refuses are reported there, and neither one makes the app restart in a loop.

Run one copy only

Keep this app at one copy. Two copies would both receive every command and both answer it.

Commands show up where?

By default the commands are registered globally, and Discord can take a while to show a global command in every server. For quick testing, add a plain variable on the app's Variables tab named DISCORD_GUILD_ID, set to your server's ID, and restart. To get the ID, turn on Developer Mode in Discord, then right-click the server and choose Copy Server ID. The commands then appear in that one server at once.

On every start the bot replaces its command list in one place only: that server when DISCORD_GUILD_ID is set, otherwise globally, so a restart never duplicates a command. Switching between the two leaves the other list registered, and your test server can show each command twice. To remove the old list, send Discord an empty list for it, as the template's README shows. Restarting the app does not remove either list.

Make your own copy

To change the bot, click Use this template on GitHub to make your own copy, then deploy that copy from the dashboard with GitHub connected. Every push to its main branch redeploys the bot. To add a command:

  1. Add its definition to definitions in lib/commands.js.
  2. Add a branch for its name in respond in the same file. It returns the reply text.
  3. Add a test in tests/commands.test.js.

Troubleshooting

  • The status page says the token is missing: add DISCORD_TOKEN as in step 3. The app restarts and connects.
  • The status page says Discord refused the token: reset the token on the Bot page, update the secret under Secrets in the dashboard sidebar, and restart the app.
  • Commands do not appear: set DISCORD_GUILD_ID as above, and check the bot was invited to that server.
  • The bot answers twice: more than one copy of the app is running. Set it back to one.

Next

Suggested guides
↑↓ to move ↵ to open Esc to close From the Dockhold docs