Back to the build log

Building a Discord bot for 10,000 users

Dogo: the Discord bot that got me into coding

Project card

Problem I wanted to learn to code by building something real. As my bot grew, I found that the public bots on Discord each did part of what servers needed (moderation, verification, self-assignable roles, a private way to contact staff) but none did all of it the way members and staff wanted.

Design An event-driven bot in Node.js using discord.js. It listens for Gateway events (ready, message, guildMemberAdd) and routes b! prefix commands through a command parser. Moderation commands check permissions first, new members go through a verification step, and a modmail system forwards reports and questions to private staff channels as embeds.

What broke I was learning to code as I built it, so things broke often and I kept fixing them. Reading the code back now, the biggest problem is the structure. Every command sits in one long switch statement with channel and role IDs written straight into it, so each new feature made the file harder to change without breaking something else.

Result It started as an experiment in 2021 and grew into a bot used across several servers. One of the biggest belonged to a creator who now has over 400,000 YouTube subscribers. I added features based on members’ suggestions and feedback.

Built with JavaScript, Node.js, discord.js v13, Discord Gateway events and permissions API, rich embeds, Heroku (worker dyno on the free plan)


Longer project page

How it started

In 2021, during the COVID-19 lockdowns, I suddenly had a lot more free time and wanted to spend it on something productive. I met a friend who was older than me and already had coding experience, and he helped me while I learnt. My first idea was just to make my own Discord bot and experiment with it.

Scaling it up

The more I learnt, the more I wanted to build something people would actually use. I noticed that the bots already on Discord didn’t do everything servers wanted, so I started adding the features members and staff were asking for. The bot spread to more servers, and one of the biggest belonged to a YouTuber who now has over 400,000 subscribers.

I was learning the language and the Discord API while people were already using the bot, so commands broke and I had to work out why and fix them while it was live. I kept going, and somewhere in that process the lockdown experiment became something I really cared about.

Where it led

This was the first thing I built that other people relied on. It taught me programming and problem solving, and showed me how much a project improves when you listen to the people using it. It’s how I found out I enjoy building things from scratch, and it’s why I stayed with tech and kept starting new projects.

What the bot does

Moderation

ban and kick check that whoever runs the command has the BAN_MEMBERS or KICK_MEMBERS permission. They refuse to act on administrators and check that the bot’s own role is high enough to act (bannable / kickable). Before removing someone, the bot DMs them the reason, and banned users also get an appeal link.

sm sets a channel’s slowmode. It rejects anything that isn’t a number and keeps the value within Discord’s limit of 1 to 21,600 seconds. purge bulk-deletes messages, then posts a confirmation that deletes itself after six seconds.

Verification and roles

New members get a welcome embed linking the rules, announcements and general channels, plus a DM telling them how to verify. When they run verify, the bot gives them the verified role, deletes their command and logs an embed to a staff channel with their account creation date, join date, status and user ID. Staff could use that to spot new or suspicious accounts.

Members can also give themselves colour roles and notification roles (announcements, giveaways, new content, chat revival) with one command, without needing a moderator.

Modmail

report <user> <reason> deletes the public message, confirms to the reporter by DM, and sends a report embed with the reported member’s details to a private staff channel. question sends a member’s question to staff, who reply privately with answer or action, and the bot delivers the reply by DM. Members could contact the team without pinging moderators in public.

Key decisions and why

I built my own bot because servers needed moderation, verification, roles and modmail in one place, set up the way they wanted. Doing it myself meant I could add what people asked for straight away.

Reports, verification logs and the help menu use Discord’s rich embeds, so staff can read the important fields at a glance.

Every moderation command checks permissions and role hierarchy before it acts. Ordinary members can’t use moderation commands, and moderators can’t act on admins.

The bot deletes report, question and verification commands as soon as they’re sent, which keeps them private and stops channels filling up with bot commands.

Hosting

The bot ran 24/7 as a worker dyno on Heroku’s free plan, started from a Procfile.

Looking back at the code

Reading the code again now, I can see a few weaknesses. Everything lives in a single index.js with a long switch statement, which made every new feature harder to add safely. Channel and role IDs are written straight into the code, so setting it up for a different server meant editing the code itself.

The help menu also lists a couple of commands under names that don’t match the real ones, because I changed commands without updating it. Error handling is uneven too. Some DMs use .catch() so a member with closed DMs doesn’t break a command, but others don’t.

What I’d do differently

  • Split commands into separate modules loaded by a command handler.
  • Move server-specific IDs into a config file so the same code could run in any server.
  • Switch to slash commands, which discord.js v13 introduced, so Discord validates arguments before they reach the bot.
  • Keep the bot token in an environment variable from the start and never commit it.
  • Handle errors on every API call that can fail.

Skills I developed

  • Programming: JavaScript, Node.js, asynchronous code with promises and async/await, event-driven programming, error handling, debugging a live system
  • Discord API: Gateway events, the permissions system and role hierarchy, embeds, DMs, bulk message deletion, channel rate limits
  • Product: gathering feature requests and feedback from real users, deciding what to build next, maintaining something people rely on

Thank you

Thank you to the friend who mentored me when I was starting out, and to the server owners and members who used the bot and told me what to build next.