A clean, modular Discord bot template with TypeScript, featuring a command class pattern and single source of truth architecture.
- Single Source of Truth: Add commands in one place, automatically available everywhere
- TypeScript: Full type safety and modern JavaScript features
- Modular Commands: Self-contained command classes with built-in validation
- Environment Validation: Comprehensive startup checks with helpful error messages
- Auto-Generated Help: Commands self-document with metadata
- Contextual Logging: Detailed logging with class and function context
- Production Ready: Error handling, validation, and clean architecture
git clone <your-repo>
cd discord-bot-template
npm install
cp .env.example .envEdit .env with your bot credentials:
DISCORD_TOKEN=your_bot_token_here
DISCORD_CLIENT_ID=your_bot_client_id_here
DEVELOPER_IDS=your_user_id_here # Optional
NODE_ENV=development # Optionalnpm run register # Register commands with Discord
npm run dev # Start development serversrc/
├── core/
│ ├── Bot.ts # Main bot class
│ ├── Command.ts # Abstract command base
│ └── CommandManager.ts # Command management
├── commands/
│ ├── index.ts # ← Command registry (single source of truth)
│ ├── PingCommand.ts # Basic example
│ ├── InfoCommand.ts # Embed example
│ ├── ExampleCommand.ts # Advanced features
│ ├── HelpCommand.ts # Auto-generated help
│ └── DevCommand.ts # Developer tools
├── services/
│ ├── Logger.ts # Contextual logging
│ ├── DiscordApi.ts # API helper
│ └── Environment.ts # Config validation
├── index.ts # Entry point
└── register.ts # Command registration
// src/commands/MyCommand.ts
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { Command, CommandHelpInfo } from '../core/Command.js';
export class MyCommand extends Command {
public readonly data = new SlashCommandBuilder()
.setName('mycommand')
.setDescription('My awesome command');
public readonly helpInfo: CommandHelpInfo = {
name: 'mycommand',
description: 'Does something awesome',
usage: '/mycommand',
examples: ['/mycommand'],
category: 'General'
};
public async execute(interaction: ChatInputCommandInteraction): Promise<void> {
await interaction.reply('Hello World!');
}
}// src/commands/index.ts
import { MyCommand } from './MyCommand.js';
export const ALL_COMMANDS: Command[] = [
// ... existing commands
new MyCommand(), // ← Add here
];That's it! Your command is automatically:
- ✅ Registered with Discord
- ✅ Available in the bot
- ✅ Listed in help system
- ✅ Validated and logged
/ping- Basic ping/pong with latency/info- Bot information and statistics/help [command]- Auto-generated help system/example <subcommand>- Advanced command examples/dev <info|test>- Developer tools (requiresDEVELOPER_IDS)
npm run build- Compile TypeScriptnpm run dev- Build and run with file watchingnpm run start- Start production servernpm run register- Register commands with Discordnpm run deploy- Build, register, and start
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
✅ | Bot token from Discord Developer Portal |
DISCORD_CLIENT_ID |
✅ | Bot client ID from Discord Developer Portal |
DEVELOPER_IDS |
❌ | Comma-separated user IDs for developer commands |
NODE_ENV |
❌ | Environment mode (defaults to production) |
This project is licensed under Apache 2.0 + the Commons Clause. In plain terms:
- ✅ Free to use as a template. Build your own Discord bots on top of it, private or public, monetized or not, at no cost.
- ✅ Forking and contributing is welcome. Fork the repo, modify the code, and open a PR. Community contributions are encouraged.
- ❌ You cannot sell the template itself. The Commons Clause means you may not sell a product or service whose value derives primarily from this template (for example, reselling it as a paid starter kit or boilerplate).
In short: build whatever bots you want with this template, just do not sell the template itself. See LICENSE for the full terms.
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request