calabasas
Type-Safe Discord for Convex

calabasasYour bots, fully typed

A CLI that generates type-safe Discord event handlers for your Convex backend. Configure once, get full TypeScript types for every message, interaction, and member event.

~/my-discord-bot

How It Works

Three commands to go from zero to type-safe Discord handlers

01

Register Your Bot

calabasas bot add

Interactive setup walks you through bot registration. Pick your intents, paste your token, and you're ready to go.

? Bot name: my-bot
? Select intents:
◉ GUILDS
◉ GUILD_MESSAGES
◉ GUILD_MEMBERS
○ GUILD_VOICE_STATES
✓ Bot registered successfully
calabasas.config.ts
export default {
  events: [
    "messageCreate",
    "guildMemberAdd",
  ],
  sync: {
    guilds: true,
    roles: true,
  }
};
02

Configure Events

calabasas.config.ts

Enable the events you need and sync tables you want. Your config is the source of truth for type generation.

03

Generate Types

calabasas generate

Creates validators, TypeScript types, and handler wrappers. Full inference from event name to payload shape.

✓ Generated discord.generated.ts
12 event handlers
47 type definitions
4 sync table schemas
1 handleDiscordEvent wrapper
Ready to import in your handlers

Config In, Types Out

Define what you need. Get autocomplete everywhere.

calabasas.config.ts
export default {
  events: [
    "messageCreate",
    "interactionCreate",
    "guildMemberAdd",
  ],
  sync: {
    guilds: true,
    channels: true,
    roles: true,
    members: true,
  }
};
convex/discord.ts
import { handleDiscordEvent } from "./discord.generated";

export const messageCreate = handleDiscordEvent(
  "messageCreate",
  async (ctx, data) => {
    // Full autocomplete ✨
    data.content
    data.author.id
    data.channelId
  }
);

12+

Events

100%

Typed

4

Sync Tables

1

CLI

Every Event, Fully Typed

Messages, interactions, voice, members — all with complete TypeScript coverage

messageCreate
interactionCreate
guildMemberAdd
voiceStateUpdate
messageReactionAdd
guildCreate
channelCreate
presenceUpdate

+ 4 more events supported

sync: true

Discord Data, Always Fresh

Enable sync tables and Calabasas automatically mirrors your Discord server data to Convex. Query guilds, channels, roles, and members with reactive subscriptions.

Discord
Servers
Channels
Roles
Members
Calabasas

Listens to Gateway events and syncs changes in real-time

Convex
guilds
channels
roles
members

Reactive Queries

Use Convex's useQuery to subscribe to Discord data. UI updates automatically when server changes.

Query with Indexes

Filter members by role, channels by type, or any field. Full Convex query power on Discord data.

Join with Your Data

Link Discord members to your users table. Build dashboards that combine Discord and app data.

Your Convex query
export const getServerMembers = query({
  args: { guildId: v.string() },
  handler: async (ctx, args) => {
    // Query synced Discord data
    return ctx.db
      .query("members")
      .withIndex("by_guild", q =>
        q.eq("guildId", args.guildId))
      .collect();
  }
});
npx calabasas init

Generate your first type-safe handler

Getting Started Guide