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
- Open the Discord developer portal and choose New Application.
- Open the Bot page and choose Reset Token. Copy it now, because Discord shows it once.
- Leave the Privileged Gateway Intents switches off. This bot does not read messages, so it needs none of them.
- Optional: switch off Public Bot on the same page, so only you can add the bot to a server.
2. Open the deploy link
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 name | Value |
|---|---|---|
discord-bot-token | DISCORD_TOKEN | The 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:
- Add its definition to
definitionsinlib/commands.js. -
Add a branch for its name in
respondin the same file. It returns the reply text. - Add a test in
tests/commands.test.js.
Troubleshooting
-
The status page says the token is missing: add
DISCORD_TOKENas 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_IDas 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.