A simple, scalable Discord bot starter built with Bun, TypeScript, and discord.js.
- Official docs: discord.js
- Core package docs: discord.js main package
- Slash command builder docs: SlashCommandBuilder
- Install dependencies:
bun install- Create a local env file from the example:
cp .env.example .env- Fill in:
DISCORD_TOKENDISCORD_CLIENT_IDMONGODB_URI(MongoDB connection string; local or Atlas)ENVIRONMENT:P= slash commands globally (production);G=DISCORD_GUILD_IDonly (development)DISCORD_GUILD_ID— required whenENVIRONMENT=G; optional whenP
-
Server logging (
/server-log): In the Discord Developer Portal → your app → Bot, enable Privileged Gateway Intents that match the features you need (at minimum Server Members Intent for join/leave, and ensure intents align with the bot code — seedocs/PROJECT_OVERVIEW.md). Misconfigured intents cause a disallowed intents gateway error. -
Dynamic voice (
/voice-chat): Admins pick a hub voice channel; members who join get a personal room (rename, user limit, role visibility via the command panel). The bot needs Manage Channels and Move Members. MongoDB collections:voicechatsettings,voicechatchannels,voicechatevents(activity timeline, kept after channels are deleted).
bun run start
bun run start:all
bun run dev
bun run deploy:commands
bun run typecheck- Register slash commands:
bun run deploy:commands- Start the bot:
bun run start- Use
/pingin Discord.
Or run deploy + bot startup together:
bun run start:allBuild the image:
docker build -t fernn-bot .Run the bot with your local env file:
docker run --rm --env-file .env fernn-botRegister commands from the container:
docker run --rm --env-file .env fernn-bot bun run deploy:commandssrc/
commands/
types/
config.ts
deploy-commands.ts
index.ts
Each command lives in its own file and exports:
databuilt withSlashCommandBuilderexecute()to handle the interaction
This keeps adding new slash commands straightforward without rewriting the bot bootstrap or deploy flow.