- TypeScript 97.3%
- JavaScript 2.7%
| .vscode | ||
| src | ||
| .editorconfig | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| bun.lock | ||
| eslint.config.js | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
Discord Bot Template
An opinionated Discord.js v14 starter that pairs Bun, TypeScript, and a modular architecture so you can focus on shipping features instead of wiring boilerplate. Commands, events, buttons, dropdowns, and modals auto-load, guards are reusable middleware, and MongoDB plus Redis connections are ready out of the box.
Highlights
- Command framework with reusable guard middleware, automatic subcommand routing, and typed error hooks (
src/structures/Command.ts). - Interaction loader that discovers buttons, dropdowns, select menus, modals, and context menu handlers from
src/interactables/**with zero manual registration. - Environment bootstrapper that creates
.envfrom.env.example, validates required keys, and even opens an editor for you when values are missing. - Built-in MongoDB client with command logging plus a Redis cache that gracefully falls back to in-memory storage.
- Bun-powered DX: watch mode via
bun --watch, fast installs, strict TypeScript config, ESLint + Prettier. - Structured logging powered by Pino with pretty console output in development and file outputs in production.
Requirements
- Bun 1.1+ (provides the runtime, package manager, and Redis bindings).
- Node.js 18+ is recommended for tooling compatibility (TypeScript, ESLint).
- A Discord application with a bot token and at least one guild you can use for development.
- MongoDB and Redis instances (local Docker containers work fine) if you plan to use the provided services.
Getting Started
-
Clone the repository and install dependencies
git clone https://github.com/0neShot101/discord-bot-template.git discord-bot-template cd discord-bot-template bun install -
Copy the example environment file and fill in your credentials
cp .env.example .env -
Start the bot in watch mode while you iterate
bun dev -
Run
bun startwhen you want to execute the compiled app, orbun run buildto emitdist/only.
Available Scripts
| Command | Description |
|---|---|
bun dev |
Runs src/index.ts in watch mode for rapid iteration. |
bun start |
Runs the bot once (no watch) via Bun runtime. |
bun run build |
Transpiles TypeScript into dist/ using tsc. |
bun run typecheck |
Runs the TypeScript compiler with --noEmit for CI. |
bun run lint |
ESLint across the repo using the flat config in eslint.config.js. |
bun run format |
Applies Prettier to every supported file. |
bun run commands deploy |
Deploy slash commands to Discord (guild or global). |
bun run commands clear |
Remove all registered commands from Discord. |
bun run commands list |
Compare local commands against what Discord has registered. |
Command Registration
Slash commands need to be registered with Discord before they appear in servers. The template handles this automatically in development and gives you a CLI for production.
Development (automatic): When NODE_ENV=development (the default), commands auto-register to your dev guild on startup. Guild-scoped commands propagate instantly so you can iterate fast. Hash-based change detection skips the API call if nothing changed.
Production (explicit): Auto-registration is off by default in production. Deploy commands when you're ready:
bun run commands deploy # auto-detects scope from NODE_ENV
bun run commands deploy --global # force global registration
bun run commands deploy --guild # force guild registration
bun run commands deploy --force # skip change detection
bun run commands clear --global # remove all global commands
bun run commands list # diff local vs registered commands
Separate dev/prod bots: Use different .env files per environment with different bot credentials. The .env is gitignored so each environment gets its own config.
Environment Variables
| Key | Required | Description |
|---|---|---|
DISCORD_TOKEN |
Yes | Bot token from the Discord Developer Portal. |
DISCORD_CLIENT_ID |
Yes | Application (bot) ID used for slash command registration. |
DISCORD_DEVELOPMENT_GUILD_ID |
Yes | Guild ID used for registering commands during development. |
MONGODB_URI |
No | MongoDB connection string (leave empty to disable). |
MONGODB_DB_NAME |
No | Database name to use once connected (leave empty to disable). |
REDIS_URL |
No | Redis connection string (falls back to in-memory cache if unavailable). |
NODE_ENV |
No | Defaults to development. Controls logging verbosity and command registration scope. |
LOG_LEVEL |
No | Overrides default Pino log level. |
AUTO_REGISTER_COMMANDS |
No | Auto-register commands on startup. Defaults to true in development, false in production. |
Tip:
src/utils/environment.tsvalidates these keys at startup, creates.envif it is missing, and attempts to open the file in your editor when required keys are absent. Fill everything out once and the template will refuse to boot with incomplete configuration, saving time later.
Project Layout
src/
index.ts # Entry point, signal handlers, client.run()
client.ts # Client instance (separate from index to avoid circular imports)
cli/ # Command registration CLI (bun run commands)
events/ # Event definitions extending src/structures/Event.ts
guards/ # Middleware such as cooldown, access, permissions
handlers/ # File system loaders for commands, events, interactions
interactables/ # Slash commands, buttons, dropdowns, modals, context menus
services/database/ # MongoDB + Redis helpers (lazy connections)
structures/ # Base classes for commands, interactions, events, guards
types/ # TypeScript type definitions
utils/ # Logging, env management, shutdown hooks, walkers
Path aliases (@utils, @structures, etc.) are defined in tsconfig.json, so imports stay concise.
Working With Commands and Interactions
- Slash commands: Create a new file under
src/interactables/commands. Export instances ofCommand(orContextMenuCommand) and call.run()with your handler. Attach guard middleware via theguardsproperty to reuse cooldowns, channel restrictions, or permission checks. - Buttons, select menus, modals, dropdowns: Place files in the matching folder under
src/interactables. Each file exportsInteractioninstances keyed by their custom IDs. The loader handles registration automatically. - Events: Add
Eventinstances tosrc/events. Setting the second constructor argument totruemarks the event as once-only (seeready.ts).
Subcommands made easy
src/utils/subCommandRouter.ts parses the builder config and routes nested subcommands before your handler executes. Use the subcommands property when creating a Command to keep large commands tidy without manual switch statements.
Data Layer
- MongoDB:
src/services/database/mongodb.tscreates a client lazily — no connection happens until a command actually queries the database. Importmongodband call.collection()anywhere. Operations are logged at debug level. Both MongoDB and its database name are optional; leave the env vars empty to disable. - Redis cache:
src/services/database/redis.tswraps Bun's Redis client. Callredis.connect()when you need it. If Redis is unreachable or unconfigured, it silently falls back to an in-memory map. - Graceful shutdown:
src/utils/shutdown.tslistens toSIGINT/SIGTERM, closes database clients, and exits cleanly to avoid dangling connections.
Deployment Notes
- Set
NODE_ENV=productionin your production.env. - Deploy slash commands before going live:
bun run commands deploy. - Ensure MongoDB and Redis are reachable from your host if you use them (cloud services, managed instances, or Docker containers with exposed ports).
- Configure log rotation by mounting
./logsor redirecting stdout wherever you deploy; production logging writes tologs/app.logandlogs/error.log. - Use
bun run buildfollowed bybun startwith a process manager (PM2, systemd) if you prefer running compiled output.
License
This project uses a source-available license that permits free non-commercial use while requiring a commercial license for revenue-generating projects. See the LICENSE file for full terms.
In short:
- Personal projects, learning, open-source contributions: go for it, just keep attribution.
- Making money with it (SaaS, paid bots, client work): reach out first.
This template aims to get you past the boring setup phase quickly. Wire your own features into the provided structures, drop your credentials into .env, and start shipping.