D

Discord Bot Architect Engine

Boost productivity using this specialized, skill, building, production. Includes structured workflows, validation checks, and reusable patterns for enterprise communication.

SkillClipticsenterprise communicationv1.0.0MIT
0 views0 copies

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

ComponentPurposeDirectory
Entry PointClient initialization, loginindex.js
CommandsSlash command definitions + handlerscommands/
EventsGateway event listenersevents/
ComponentsButton/menu/modal handlerscomponents/
ServicesBusiness logic, database accessservices/
UtilsShared helpers, embed buildersutils/

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

ParameterDescriptionExample
tokenDiscord bot token (from Developer Portal)process.env.DISCORD_TOKEN
client_idApplication client IDprocess.env.CLIENT_ID
guild_idDevelopment server ID (for testing)process.env.GUILD_ID
intentsGateway intents to enable["Guilds", "GuildMessages"]
db_providerDatabase for persistent features"sqlite" / "mongodb"
log_channelChannel ID for bot logging"123456789012345678"

Best Practices

  1. Register slash commands separately from bot startup — Use a dedicated deploy-commands.js script that calls REST.put() to register commands. Running registration on every bot start wastes API calls and hits rate limits on large bots.

  2. Use ephemeral replies for sensitive responses — Moderation actions, personal stats, and error messages should use ephemeral: true so only the invoking user sees them. This keeps channels clean and avoids exposing private information.

  3. 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.

  4. Handle interaction timeouts explicitly — Discord requires a response within 3 seconds. For operations that take longer, call interaction.deferReply() immediately, then use interaction.editReply() when the result is ready. Unhandled timeouts crash the interaction silently.

  5. Store the bot token in environment variables, never in code — Use .env files locally and environment variables in production. Add .env to .gitignore before 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.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates