
# [Bot Name]

A Discord bot. Slash commands, buttons, modals. TypeScript. Runs on a single VM.

## Source of truth
Code on GitHub. Deployed to a tiny Fly.io VM (shared-cpu-1x, 256MB is plenty for most bots). The deployed binary is what answers Discord events.

## Tech stack
Node 22 + TypeScript + discord.js 14. Slash commands registered via the Discord REST API on deploy. Storage in a SQLite file (better-sqlite3) for v0; swap to Postgres when you need multi-instance. Logs to Pino + Fly logs.

## Deploy
- Slash command sync: `npm run register` (one-off when commands change)
- Deploy: `fly deploy` from local
- Logs: `fly logs`

## File map
- `src/index.ts` client setup, event router, login
- `src/commands/` one file per slash command (`/ping.ts`, `/setup.ts`)
- `src/interactions/` button + modal handlers
- `src/events/` Discord event handlers (`messageCreate`, `guildCreate`)
- `src/db.ts` better-sqlite3 wrapper
- `src/lib/logger.ts` Pino setup
- `scripts/register-commands.ts` POSTs slash command schemas to Discord
- `fly.toml`

## .env keys
- `DISCORD_TOKEN` bot token from Developer Portal
- `DISCORD_CLIENT_ID` application ID
- `DISCORD_GUILD_ID` your test server (for fast iteration). Remove for global commands in prod.
- `DATABASE_PATH` defaults `./data/bot.db`

## Hard rules
- Required gateway intents declared explicitly. `GUILDS` + whatever else you actually need. Don't request `MESSAGE_CONTENT` unless you use it (Discord asks for verification above 100 guilds).
- Slash commands have a 3-second initial response window. If your handler does work, use `interaction.deferReply()` immediately and `editReply()` later.
- Every command file exports `{ data, execute }`. The router auto-loads them. No manual switch statements.
- DB writes are synchronous (better-sqlite3 is sync); that's fine for a single-instance bot. Don't add async if you don't need it.
- Bot token never committed. `.env` is `.gitignore`d.
- Use ephemeral replies (`flags: MessageFlags.Ephemeral`) for anything per-user.

## Recent significant changes
- 2026-04-30: Scaffolded. Locked: discord.js 14 (still the boring choice), better-sqlite3 over knex/Drizzle (single-file simplicity), Fly.io over Railway (cheaper at sleep).

## Next session: start here
1. Create application at `https://discord.com/developers/applications`. Save `DISCORD_CLIENT_ID`.
2. Add bot, copy `DISCORD_TOKEN` into `.env`.
3. OAuth URL Generator -> scopes: `bot applications.commands`. Pick permissions. Invite to test server.
4. `npm run register` to upload slash commands.
5. `npm run dev` to test locally before `fly deploy`.
