Discord Bot Architect Engine
Boost productivity using this specialized, skill, building, production. Includes structured workflows, validation checks, and reusable patterns for enterprise communication.
Discord Bot Architect Engine
A comprehensive skill for designing and building Discord bots using Discord.js v14 — covering slash command architecture, event handling, interaction collectors, embed builders, database integration, and deployment to production hosting.
When to Use This Skill
Choose Discord Bot Architect Engine when you need to:
- Build a Discord bot from scratch with modern slash commands
- Design scalable command and event handler architecture
- Implement interactive components (buttons, menus, modals)
- Add database-backed features (XP systems, moderation logs, custom configs)
- Deploy and host a Discord bot in production
Consider alternatives when:
- You need a simple webhook integration (use Discord webhooks directly)
- You're building a Telegram or Slack bot (use platform-specific skills)
- You need real-time voice processing (use a voice API skill)
Quick Start
# Initialize a Discord bot project mkdir my-discord-bot && cd my-discord-bot npm init -y npm install discord.js dotenv
// index.js — Bot entry point const { Client, GatewayIntentBits, Collection } = require("discord.js"); const fs = require("fs"); const path = require("path"); require("dotenv").config(); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, ], }); // Load commands client.commands = new Collection(); const commandsPath = path.join(__dirname, "commands"); const commandFiles = fs.readdirSync(commandsPath).filter(f => f.endsWith(".js")); for (const file of commandFiles) { const command = require(path.join(commandsPath, file)); client.commands.set(command.data.name, command); } // Handle interactions client.on("interactionCreate", async (interaction) => { if (!interaction.isChatInputCommand()) return; const command = client.commands.get(interaction.commandName); if (!command) return; try { await command.execute(interaction); } catch (error) { console.error(error); await interaction.reply({ content: "Something went wrong.", ephemeral: true, }); } }); client.once("ready", () => { console.log(`Logged in as ${client.user.tag}`); }); client.login(process.env.DISCORD_TOKEN);
// commands/ping.js — Example slash command const { SlashCommandBuilder } = require("discord.js"); module.exports = { data: new SlashCommandBuilder() .setName("ping") .setDescription("Check bot latency"), async execute(interaction) { const sent = await interaction.reply({ content: "Pinging...", fetchReply: true, }); const latency = sent.createdTimestamp - interaction.createdTimestamp; await interaction.editReply( `Pong! Latency: ${latency}ms | API: ${interaction.client.ws.ping}ms` ); }, };
Core Concepts
Bot Architecture
| Component | Purpose | Directory |
|---|---|---|
| Entry Point | Client initialization, login | index.js |
| Commands | Slash command definitions + handlers | commands/ |
| Events | Gateway event listeners | events/ |
| Components | Button/menu/modal handlers | components/ |
| Services | Business logic, database access | services/ |
| Utils | Shared helpers, embed builders | utils/ |
Interactive Components
// commands/poll.js — Button interactions const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, } = require("discord.js"); module.exports = { data: new SlashCommandBuilder() .setName("poll") .setDescription("Create a quick poll") .addStringOption(opt => opt.setName("question").setDescription("Poll question").setRequired(true) ), async execute(interaction) { const question = interaction.options.getString("question"); const embed = new EmbedBuilder() .setTitle("Poll") .setDescription(question) .setColor(0x2563EB) .addFields( { name: "👍 Yes", value: "0 votes", inline: true }, { name: "👎 No", value: "0 votes", inline: true } ); const row = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId("poll_yes") .setLabel("Yes") .setStyle(ButtonStyle.Success), new ButtonBuilder() .setCustomId("poll_no") .setLabel("No") .setStyle(ButtonStyle.Danger) ); await interaction.reply({ embeds: [embed], components: [row] }); }, };
Embed Builder Patterns
// utils/embeds.js const { EmbedBuilder } = require("discord.js"); function successEmbed(title, description) { return new EmbedBuilder() .setColor(0x10B981) .setTitle(`✅ ${title}`) .setDescription(description) .setTimestamp(); } function errorEmbed(title, description) { return new EmbedBuilder() .setColor(0xEF4444) .setTitle(`❌ ${title}`) .setDescription(description) .setTimestamp(); } module.exports = { successEmbed, errorEmbed };
Configuration
| Parameter | Description | Example |
|---|---|---|
token | Discord bot token (from Developer Portal) | process.env.DISCORD_TOKEN |
client_id | Application client ID | process.env.CLIENT_ID |
guild_id | Development server ID (for testing) | process.env.GUILD_ID |
intents | Gateway intents to enable | ["Guilds", "GuildMessages"] |
db_provider | Database for persistent features | "sqlite" / "mongodb" |
log_channel | Channel ID for bot logging | "123456789012345678" |
Best Practices
-
Register slash commands separately from bot startup — Use a dedicated
deploy-commands.jsscript that callsREST.put()to register commands. Running registration on every bot start wastes API calls and hits rate limits on large bots. -
Use ephemeral replies for sensitive responses — Moderation actions, personal stats, and error messages should use
ephemeral: trueso only the invoking user sees them. This keeps channels clean and avoids exposing private information. -
Implement a command cooldown system — Without cooldowns, users can spam commands and overload your bot. Track command usage per user with a Map or database, and reject requests within the cooldown window with a friendly message.
-
Handle interaction timeouts explicitly — Discord requires a response within 3 seconds. For operations that take longer, call
interaction.deferReply()immediately, then useinteraction.editReply()when the result is ready. Unhandled timeouts crash the interaction silently. -
Store the bot token in environment variables, never in code — Use
.envfiles locally and environment variables in production. Add.envto.gitignorebefore your first commit. Leaked tokens allow anyone to control your bot, and Discord automatically revokes tokens found in public repositories.
Common Issues
Bot doesn't respond to slash commands — Verify the bot was invited with the applications.commands scope (not just bot). Re-run the deploy-commands script after changing command definitions. Check that the interactionCreate event listener correctly matches command names with client.commands.get().
"Unknown interaction" errors in production — This happens when the bot takes longer than 3 seconds to respond. Use deferReply() at the start of any command that involves database queries, API calls, or computation. The deferred state gives you 15 minutes to send the final response.
Button/menu interactions stop working after restart — If you use createMessageComponentCollector, collectors are in-memory and die on restart. For persistent interactions, handle them in the interactionCreate event by checking interaction.customId patterns, not in collectors. Reserve collectors for short-lived interactions like confirmation dialogs.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.