Discord Bot Architect

Discord bot architect

by davila7 · MIT license · ★ 32,299 on GitHub

Discord bot architect cover

Specialized skill for building production-ready Discord bots. Covers Discord.js (JavaScript) and Pycord (Python), gateway intents, slash commands, interactive components, rate limiting, and sharding.

---
name: discord-bot-architect
description: "Specialized skill for building production-ready Discord bots. Covers Discord.js (JavaScript) and Pycord (Python), gateway intents, slash commands, interactive components, rate limiting, and sharding."
source: vibeship-spawner-skills (Apache 2.0)
---

# Discord Bot Architect

## Patterns

### Discord.js v14 Foundation

Modern Discord bot setup with Discord.js v14 and slash commands

**When to use**: ['Building Discord bots with JavaScript/TypeScript', 'Need full gateway connection with events', 'Building bots with complex interactions']

```javascript
```javascript

Overview

Modern Discord bot setup with Discord.js v14 and slash commands

Manual install (npx, ZIP)
Claude Codenpx skills add davila7/claude-code-templates --skill discord-bot-architect -g -a claude-code
Claude Code (degit)npx degit davila7/claude-code-templates/cli-tool/components/skills/enterprise-communication/discord-bot-architect#main ~/.claude/skills/discord-bot-architect
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md8.0 KB
Read SKILL.md here
davila7/main1 file shown
SKILL.md
Show the full text278 lines

Discord Bot Architect

Patterns

Discord.js v14 Foundation

Modern Discord bot setup with Discord.js v14 and slash commands

When to use: ['Building Discord bots with JavaScript/TypeScript', 'Need full gateway connection with events', 'Building bots with complex interactions']

```javascript
// src/index.js
const { Client, Collection, GatewayIntentBits, Events } = require('discord.js');
const fs = require('node:fs');
const path = require('node:path');
require('dotenv').config();

// Create client with minimal required intents
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    // Add only what you need:
    // GatewayIntentBits.GuildMessages,
    // GatewayIntentBits.MessageContent,  // PRIVILEGED - avoid if possible
  ]
});

// 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 filePath = path.join(commandsPath, file);
  const command = require(filePath);
  if ('data' in command && 'execute' in command) {
    client.commands.set(command.data.name, command);
  }
}

// Load events
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(f => f.endsWith('.js'));

for (const file of eventFiles) {
  const filePath = path.join(eventsPath, file);
  const event = require(filePath);
  if (event.once) {
    client.once(event.name, (...args) => event.execute(...args));
  } else {
    client.on(event.name, (...args) => event.execute(...args));
  }
}

client.login(process.env.DISCORD_TOKEN);
// src/commands/ping.js
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Replies with Pong!'),

  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`);
  }
};
// src/events/interactionCreate.js
const { Events } = require('discord.js');

module.exports = {
  name: Event
Pycord Bot Foundation

Discord bot with Pycord (Python) and application commands

When to use: ['Building Discord bots with Python', 'Prefer async/await patterns', 'Need good slash command support']

```python
# main.py
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

# Configure intents - only enable what you need
intents = discord.Intents.default()
# intents.message_content = True  # PRIVILEGED - avoid if possible
# intents.members = True          # PRIVILEGED

bot = commands.Bot(
    command_prefix="!",  # Legacy, prefer slash commands
    intents=intents
)

@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")
    # Sync commands (do this carefully - see sharp edges)
    # await bot.sync_commands()

# Slash command
@bot.slash_command(name="ping", description="Check bot latency")
async def ping(ctx: discord.ApplicationContext):
    latency = round(bot.latency * 1000)
    await ctx.respond(f"Pong! Latency: {latency}ms")

# Slash command with options
@bot.slash_command(name="greet", description="Greet a user")
async def greet(
    ctx: discord.ApplicationContext,
    user: discord.Option(discord.Member, "User to greet"),
    message: discord.Option(str, "Custom message", required=False)
):
    msg = message or "Hello!"
    await ctx.respond(f"{user.mention}, {msg}")

# Load cogs
for filename in os.listdir("./cogs"):
    if filename.endswith(".py"):
        bot.load_extension(f"cogs.{filename[:-3]}")

bot.run(os.environ["DISCORD_TOKEN"])
# cogs/general.py
import discord
from discord.ext import commands

class General(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.slash_command(name="info", description="Bot information")
    async def info(self, ctx: discord.ApplicationContext):
        embed = discord.Embed(
            title="Bot Info",
            description="A helpful Discord bot",
            color=discord.Color.blue()
        )
        embed.add_field(name="Servers", value=len(self.bot.guilds))
        embed.add_field(name="Latency", value=f"{round(self.bot.latency * 1000)}ms")
        await ctx.respond(embed=embed)

    @commands.Cog.
Interactive Components Pattern

Using buttons, select menus, and modals for rich UX

When to use: ['Need interactive user interfaces', 'Collecting user input beyond slash command options', 'Building menus, confirmations, or forms']

```javascript
// Discord.js - Buttons and Select Menus
const {
  SlashCommandBuilder,
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  StringSelectMenuBuilder,
  ModalBuilder,
  TextInputBuilder,
  TextInputStyle
} = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('menu')
    .setDescription('Shows an interactive menu'),

  async execute(interaction) {
    // Button row
    const buttonRow = new ActionRowBuilder()
      .addComponents(
        new ButtonBuilder()
          .setCustomId('confirm')
          .setLabel('Confirm')
          .setStyle(ButtonStyle.Primary),
        new ButtonBuilder()
          .setCustomId('cancel')
          .setLabel('Cancel')
          .setStyle(ButtonStyle.Danger),
        new ButtonBuilder()
          .setLabel('Documentation')
          .setURL('https://discord.js.org')
          .setStyle(ButtonStyle.Link)  // Link buttons don't emit events
      );

    // Select menu row (one per row, takes all 5 slots)
    const selectRow = new ActionRowBuilder()
      .addComponents(
        new StringSelectMenuBuilder()
          .setCustomId('select-role')
          .setPlaceholder('Select a role')
          .setMinValues(1)
          .setMaxValues(3)
          .addOptions([
            { label: 'Developer', value: 'dev', emoji: '💻' },
            { label: 'Designer', value: 'design', emoji: '🎨' },
            { label: 'Community', value: 'community', emoji: '🎉' }
          ])
      );

    await interaction.reply({
      content: 'Choose an option:',
      components: [buttonRow, selectRow]
    });

    // Collect responses
    const collector = interaction.channel.createMessageComponentCollector({
      filter: i => i.user.id === interaction.user.id,
      time: 60_000  // 60 seconds timeout
    });

    collector.on('collect', async i => {
      if (i.customId === 'confirm') {
        await i.update({ content: 'Confirmed!', components: [] });
        collector.stop();
      } else if (i.custo

Anti-Patterns

❌ Message Content for Commands

Why bad: Message Content Intent is privileged and deprecated for bot commands. Slash commands are the intended approach.

❌ Syncing Commands on Every Start

Why bad: Command registration is rate limited. Global commands take up to 1 hour to propagate. Syncing on every start wastes API calls and can hit limits.

❌ Blocking the Event Loop

Why bad: Discord gateway requires regular heartbeats. Blocking operations cause missed heartbeats and disconnections.

⚠️ Sharp Edges

Issue Severity Solution
Issue critical ## Acknowledge immediately, process later
Issue critical ## Step 1: Enable in Developer Portal
Issue high ## Use a separate deploy script (not on startup)
Issue critical ## Never hardcode tokens
Issue high ## Generate correct invite URL
Issue medium ## Development: Use guild commands
Issue medium ## Never block the event loop
Issue medium ## Show modal immediately
1---
2name: discord-bot-architect
3description: "Specialized skill for building production-ready Discord bots. Covers Discord.js (JavaScript) and Pycord (Python), gateway intents, slash commands, interactive components, rate limiting, and sharding."
4source: vibeship-spawner-skills (Apache 2.0)
5---
6 
7# Discord Bot Architect
8 
9## Patterns
10 
11### Discord.js v14 Foundation
12 
13Modern Discord bot setup with Discord.js v14 and slash commands
14 
15**When to use**: ['Building Discord bots with JavaScript/TypeScript', 'Need full gateway connection with events', 'Building bots with complex interactions']
16 
17```javascript
18```javascript
19// src/index.js
20const { Client, Collection, GatewayIntentBits, Events } = require('discord.js');
21const fs = require('node:fs');
22const path = require('node:path');
23require('dotenv').config();
24 
25// Create client with minimal required intents
26const client = new Client({
27 intents: [
28 GatewayIntentBits.Guilds,
29 // Add only what you need:
30 // GatewayIntentBits.GuildMessages,
31 // GatewayIntentBits.MessageContent, // PRIVILEGED - avoid if possible
32 ]
33});
34 
35// Load commands
36client.commands = new Collection();
37const commandsPath = path.join(__dirname, 'commands');
38const commandFiles = fs.readdirSync(commandsPath).filter(f => f.endsWith('.js'));
39 
40for (const file of commandFiles) {
41 const filePath = path.join(commandsPath, file);
42 const command = require(filePath);
43 if ('data' in command && 'execute' in command) {
44 client.commands.set(command.data.name, command);
45 }
46}
47 
48// Load events
49const eventsPath = path.join(__dirname, 'events');
50const eventFiles = fs.readdirSync(eventsPath).filter(f => f.endsWith('.js'));
51 
52for (const file of eventFiles) {
53 const filePath = path.join(eventsPath, file);
54 const event = require(filePath);
55 if (event.once) {
56 client.once(event.name, (...args) => event.execute(...args));
57 } else {
58 client.on(event.name, (...args) => event.execute(...args));
59 }
60}
61 
62client.login(process.env.DISCORD_TOKEN);
63```
64 
65```javascript
66// src/commands/ping.js
67const { SlashCommandBuilder } = require('discord.js');
68 
69module.exports = {
70 data: new SlashCommandBuilder()
71 .setName('ping')
72 .setDescription('Replies with Pong!'),
73 
74 async execute(interaction) {
75 const sent = await interaction.reply({
76 content: 'Pinging...',
77 fetchReply: true
78 });
79 
80 const latency = sent.createdTimestamp - interaction.createdTimestamp;
81 await interaction.editReply(`Pong! Latency: ${latency}ms`);
82 }
83};
84```
85 
86```javascript
87// src/events/interactionCreate.js
88const { Events } = require('discord.js');
89 
90module.exports = {
91 name: Event
92```
93 
94### Pycord Bot Foundation
95 
96Discord bot with Pycord (Python) and application commands
97 
98**When to use**: ['Building Discord bots with Python', 'Prefer async/await patterns', 'Need good slash command support']
99 
100```python
101```python
102# main.py
103import os
104import discord
105from discord.ext import commands
106from dotenv import load_dotenv
107 
108load_dotenv()
109 
110# Configure intents - only enable what you need
111intents = discord.Intents.default()
112# intents.message_content = True # PRIVILEGED - avoid if possible
113# intents.members = True # PRIVILEGED
114 
115bot = commands.Bot(
116 command_prefix="!", # Legacy, prefer slash commands
117 intents=intents
118)
119 
120@bot.event
121async def on_ready():
122 print(f"Logged in as {bot.user}")
123 # Sync commands (do this carefully - see sharp edges)
124 # await bot.sync_commands()
125 
126# Slash command
127@bot.slash_command(name="ping", description="Check bot latency")
128async def ping(ctx: discord.ApplicationContext):
129 latency = round(bot.latency * 1000)
130 await ctx.respond(f"Pong! Latency: {latency}ms")
131 
132# Slash command with options
133@bot.slash_command(name="greet", description="Greet a user")
134async def greet(
135 ctx: discord.ApplicationContext,
136 user: discord.Option(discord.Member, "User to greet"),
137 message: discord.Option(str, "Custom message", required=False)
138):
139 msg = message or "Hello!"
140 await ctx.respond(f"{user.mention}, {msg}")
141 
142# Load cogs
143for filename in os.listdir("./cogs"):
144 if filename.endswith(".py"):
145 bot.load_extension(f"cogs.{filename[:-3]}")
146 
147bot.run(os.environ["DISCORD_TOKEN"])
148```
149 
150```python
151# cogs/general.py
152import discord
153from discord.ext import commands
154 
155class General(commands.Cog):
156 def __init__(self, bot):
157 self.bot = bot
158 
159 @commands.slash_command(name="info", description="Bot information")
160 async def info(self, ctx: discord.ApplicationContext):
161 embed = discord.Embed(
162 title="Bot Info",
163 description="A helpful Discord bot",
164 color=discord.Color.blue()
165 )
166 embed.add_field(name="Servers", value=len(self.bot.guilds))
167 embed.add_field(name="Latency", value=f"{round(self.bot.latency * 1000)}ms")
168 await ctx.respond(embed=embed)
169 
170 @commands.Cog.
171```
172 
173### Interactive Components Pattern
174 
175Using buttons, select menus, and modals for rich UX
176 
177**When to use**: ['Need interactive user interfaces', 'Collecting user input beyond slash command options', 'Building menus, confirmations, or forms']
178 
179```python
180```javascript
181// Discord.js - Buttons and Select Menus
182const {
183 SlashCommandBuilder,
184 ActionRowBuilder,
185 ButtonBuilder,
186 ButtonStyle,
187 StringSelectMenuBuilder,
188 ModalBuilder,
189 TextInputBuilder,
190 TextInputStyle
191} = require('discord.js');
192 
193module.exports = {
194 data: new SlashCommandBuilder()
195 .setName('menu')
196 .setDescription('Shows an interactive menu'),
197 
198 async execute(interaction) {
199 // Button row
200 const buttonRow = new ActionRowBuilder()
201 .addComponents(
202 new ButtonBuilder()
203 .setCustomId('confirm')
204 .setLabel('Confirm')
205 .setStyle(ButtonStyle.Primary),
206 new ButtonBuilder()
207 .setCustomId('cancel')
208 .setLabel('Cancel')
209 .setStyle(ButtonStyle.Danger),
210 new ButtonBuilder()
211 .setLabel('Documentation')
212 .setURL('https://discord.js.org')
213 .setStyle(ButtonStyle.Link) // Link buttons don't emit events
214 );
215 
216 // Select menu row (one per row, takes all 5 slots)
217 const selectRow = new ActionRowBuilder()
218 .addComponents(
219 new StringSelectMenuBuilder()
220 .setCustomId('select-role')
221 .setPlaceholder('Select a role')
222 .setMinValues(1)
223 .setMaxValues(3)
224 .addOptions([
225 { label: 'Developer', value: 'dev', emoji: '💻' },
226 { label: 'Designer', value: 'design', emoji: '🎨' },
227 { label: 'Community', value: 'community', emoji: '🎉' }
228 ])
229 );
230 
231 await interaction.reply({
232 content: 'Choose an option:',
233 components: [buttonRow, selectRow]
234 });
235 
236 // Collect responses
237 const collector = interaction.channel.createMessageComponentCollector({
238 filter: i => i.user.id === interaction.user.id,
239 time: 60_000 // 60 seconds timeout
240 });
241 
242 collector.on('collect', async i => {
243 if (i.customId === 'confirm') {
244 await i.update({ content: 'Confirmed!', components: [] });
245 collector.stop();
246 } else if (i.custo
247```
248 
249## Anti-Patterns
250 
251### ❌ Message Content for Commands
252 
253**Why bad**: Message Content Intent is privileged and deprecated for bot commands.
254Slash commands are the intended approach.
255 
256### ❌ Syncing Commands on Every Start
257 
258**Why bad**: Command registration is rate limited. Global commands take up to 1 hour
259to propagate. Syncing on every start wastes API calls and can hit limits.
260 
261### ❌ Blocking the Event Loop
262 
263**Why bad**: Discord gateway requires regular heartbeats. Blocking operations
264cause missed heartbeats and disconnections.
265 
266## ⚠️ Sharp Edges
267 
268| Issue | Severity | Solution |
269|-------|----------|----------|
270| Issue | critical | ## Acknowledge immediately, process later |
271| Issue | critical | ## Step 1: Enable in Developer Portal |
272| Issue | high | ## Use a separate deploy script (not on startup) |
273| Issue | critical | ## Never hardcode tokens |
274| Issue | high | ## Generate correct invite URL |
275| Issue | medium | ## Development: Use guild commands |
276| Issue | medium | ## Never block the event loop |
277| Issue | medium | ## Show modal immediately |
278 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 32,299
Checked
Source
davila7/claude-code-templates ↗
Creator
davila7 · 212 listings
View creator

Similar skills

See all →
SkillDiscord Channel Setupanthropics/claude-plugins-official · by anthropicsSet up the Discord channel — save the bot token and review access policy. Use when the user pastes a Discord bot token, asks to configure Discord, asks "how do I set this up" or "who can reach me," or wants to check channel status.★ 37.6k GitHub starsSkillDiscord Analytics Readerhimself65/finance-skills · by himself65Read Discord for financial research using opencli (read-only). Use this skill whenever the user wants to read Discord channels, search for messages in trading servers, view guild/channel info, monitor crypto or market discussion groups, or gather financial sentiment from Discord. Triggers include: "check my Discord", "search Discord for", "read Discord messages", what's happening in the trading Discord", "show Discord channels", "list my servers", Discord sentiment on BTC", "what are people saying in Discord about AAPL", monitor crypto Discord", any mention of Discord in context of reading financial news, market research, or trading community discussions. This skill is READ-ONLY — it does NOT support sending messages, reacting, or any write operations.★ 3.3k GitHub starsSkillPersonal Authority Builderguia-matthieu/clawfu-skills · by guia-matthieuApply Russell Brunson's Expert Secrets framework to build a mass movement around expertise — create a charismatic leader persona, design a new-opportunity offer, craft belief-breaking stories, and structure a Perfect Webinar that converts. Use when: positioning as an expert to monetize knowledge, creating an online course or coaching program, designing a webinar sales presentation, building a tribe with an identity and cause, crafting an Epiphany Bridge origin story, or packaging expertise into a value ladder.★ 151 GitHub starsSkillCommunity Post Generatormarcosmodly/marketing-skill · by marcosmodlyWrites Reddit, Product Hunt, Hacker News (Show HN), Indie Hackers (Show IH), dev.to (#showdev), Discord, Slack, and Telegram posts that follow each community's actual rules. Researches that specific subreddit's or site's rules and what currently works there live, verifying each source is about the named target, then gives a plain Go/No-Go and only drafts if the post is welcome, written to read like a person wrote it and in the platform's own format (Slack mrkdwn, Telegram HTML). For Discord, Slack, and private Telegram groups, which have no public rules page, it asks the user for the rules instead of guessing. Use when the user wants to post or promote something in a subreddit, launch on Product Hunt, write a Show HN or Show IH, post on dev.to, or share in a Discord server, Slack workspace, Telegram channel or group, or any other rules-driven community or forum. Not for LinkedIn, X, Instagram, or Facebook posts.★ 42 GitHub starsSkillYouTube Comment Analyzersergebulaev/youtube-skills · by sergebulaevRead your YouTube audience from the comments: pull commenters and top comments on any video, surface recurring questions and themes (content ideas), repeat commenters (superfans), sentiment, and which comments to reply to or pin. Also channel stats and niche trending, via the free official YouTube Data API. Triggers on "who commented on my video", "analyze my comments", "audience insights", "trending on YouTube". Not for writing a community post (use yt-community-post-writer).★ 36 GitHub starsSkillCommunity Post Writersergebulaev/youtube-skills · by sergebulaevWrite YouTube community-tab posts: text updates, polls, image-caption posts, and questions that drive comments and bring subscribers back between video uploads. Tuned to the community tab's role as a low-friction touchpoint that keeps a channel warm and feeds session signals. Returns a copy-paste block (community posts have no publishing API, so this is always manual by design). Use to write a community post or poll. Not for video titles or descriptions (use yt-title-optimizer and yt-description-writer).★ 36 GitHub stars

More from davila7

Skill2D Game Developmentdavila7/claude-code-templates · by davila72D game development principles. Sprites, tilemaps, physics, camera.★ 32.3k GitHub starsSkill3D Game Development Principlesdavila7/claude-code-templates · by davila73D game development principles. Rendering, shaders, physics, cameras.★ 32.3k GitHub starsSkill3D Web Experience Builderdavila7/claude-code-templates · by davila7Expert in building 3D experiences for the web - Three.js, React Three Fiber, Spline, WebGL, and interactive 3D scenes. Covers product configurators, 3D portfolios, immersive websites, and bringing depth to web experiences. Use when: 3D website, three.js, WebGL, react three fiber, 3D experience.★ 32.3k GitHub starsSkillSplit Test Setupdavila7/claude-code-templates · by davila7When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," or "hypothesis." For tracking implementation, see analytics-tracking.★ 32.3k GitHub starsAgentResearch Literature Synthesizerdavila7/claude-code-templates · by davila7Academic research synthesis specialist. Use PROACTIVELY for comprehensive research on academic topics, literature reviews, technical investigations, and well-cited analysis combining multiple sources. <example>Context: A podcast episode needs a segment grounded in peer-reviewed evidence with formal citations. user: "Research the current state of transformer efficiency techniques for the episode, with proper academic citations." assistant: "I'll use the academic-research-synthesizer agent to search arXiv and Semantic Scholar, extract full-text findings via WebFetch, and produce a cited literature synthesis with confidence levels." <commentary>Use academic-research-synthesizer (not comprehensive-researcher) when the episode segment needs peer-reviewed sourcing, formal citation format, and explicit confidence tagging rather than general-purpose multi-source coverage.</commentary></example> <example>Context: The episode-orchestrator has routed a "literature review" request for a technical deep-dive segment. user: "Summarize the research landscape on federated learning privacy guarantees." assistant: "I'll invoke academic-research-synthesizer to systematically search academic sources, note peer-review status per source, and synthesize consensus vs. open debates."</example>★ 32.3k GitHub starsAgentAcademic Research Specialistdavila7/claude-code-templates · by davila7Academic research specialist for scholarly sources, peer-reviewed papers, and academic literature. Use PROACTIVELY for research paper analysis, literature reviews, citation tracking, and academic methodology evaluation. <example>Context: The research-orchestrator has kicked off Phase 4 parallel research on 'efficacy of intermittent fasting' and needs peer-reviewed evidence. user: "Find the academic evidence on intermittent fasting outcomes." assistant: "I'll use the academic-researcher agent to search Semantic Scholar, PubMed, and OpenAlex for peer-reviewed studies and write structured findings to academic-research.md." <commentary>The request is specifically for scholarly/peer-reviewed evidence rather than general web coverage or code, so academic-researcher (not web-researcher or technical-researcher) is the right specialist.</commentary></example> <example>Context: The user wants a literature review comparing methodologies across studies on a topic. user: "Can you review the literature on transformer model interpretability and identify research gaps?" assistant: "Let me invoke the academic-researcher agent to pull foundational and recent papers, extract methodologies, and surface open research gaps." <commentary>Literature review, methodology extraction, and research-gap identification are core academic-researcher capabilities, distinct from technical-researcher's focus on code repositories and implementations.</commentary></example>★ 32.3k GitHub stars