Context

An active Discord server always ends up with the same needs: make people want to come back, keep it lively without spending every evening on it, moderate without arbitrariness. The usual answer is to stack five or six public bots, each with its own configuration, limits and subscription.

Axobot replaces that stack with a single bot, built for actual use rather than for a feature catalogue. 36 modules, 52 slash commands, one shared database, and above all a very short feedback loop: what’s missing one evening often ships the following week.

What the bot does

  • Gamification: XP from messages and voice time, 13 level roles granted automatically, leaderboards, idle detection, XP betting.
  • 80 achievements with cascading, idempotent unlocks: replaying the same event never grants a reward twice.
  • Casino and virtual economy: slots, blackjack, progressive jackpot, shop.
  • Esports tracking: Valorant and TFT stats synced automatically, leaderboards in voice channels, predictions, Formula 1 following.
  • Community rituals: a weekly game night with RSVPs and DM reminders, quizzes, giveaways, birthdays, countdowns, recaps and yearly rewinds.
  • Moderation: traceable sanctions, audit log, suggestion box and bug reports.
  • Conversational AI: the bot answers when mentioned, with a deliberate tone, powered by Llama 3.3 70B through Groq.

Architecture

The project is an npm workspaces monorepo in TypeScript ESM on Node 22: the community bot, the Axoquest RPG bot and its web app share four common libraries (database access, services, types, utilities). discord.js v14, PostgreSQL via Prisma (85 models), Zod validation, Pino logging, Vitest tests, running in production under PM2.

A few conventions mattered more than the choice of building blocks:

  • A 400-line cap per file, enforced in CI. The rule looks arbitrary; in practice it is what kept modules from turning into unreadable blocks after 230 releases.
  • Services exported as objects, not classes. No dependency injection to wire up, and tests that just pass arguments.
  • upsert everywhere on user profiles. Several commands can target the same profile in parallel; this removes the write race at the root.
  • Fire-and-forget side effects. A failing achievement or jackpot update must never fail the command that triggered it.
  • No hard-coded Discord IDs: everything goes through configuration, which is what made the move to multi-server possible.

Quality and delivery

The testing rule is simple and held to: business logic ships with its tests, bug fixes ship with a regression test, and we test behaviour, not implementation. Adapters (commands, embeds, repositories) are deliberately left untested: covering them is expensive and catches nothing.

CI checks types, lint (Biome), tests and file sizes before every merge. The 230 published releases follow strict semantic versioning, and every release note is written for players, free of technical jargon. A VitePress site covers both the user guide and the technical documentation.

Axobot documentation: command reference with a side table of contents.

Where it leads

Axobot was built for one server. Making it installable by any community required a full architectural rewrite: that’s Axo’s Corp, covered at the end of the Axoquest case study.

Key deliverables

  • Multi-module Discord bot: 36 modules, 52 slash commands
  • 85-model PostgreSQL schema with hand-written migrations
  • Idempotent achievement system with cascading unlocks
  • Riot Games, Spotify and Groq integrations
  • CI/CD pipeline, PM2 process management, local Docker stack
  • User and technical documentation (VitePress), 230 release notes