Contributing
Conventions, branches, and the checks your PR needs to pass.
Contributions are welcome. A little house style keeps the codebase consistent.
Conventions
- ESM everywhere. The project is
"type": "module"; local imports use.jsextensions even in TypeScript source (import env from "./utils/env.js"). - Strict TypeScript.
noUnusedLocals,noUnusedParameters,noImplicitReturns, andnoUncheckedIndexedAccessare all on. - Use the logger. Import
loggerfromsrc/utils/logger.tsand pick the right sub-logger (logger.commands.*,logger.database.*, etc.) — never rawconsole.log. - Max line length 120 (enforced by ESLint).
- Bun only — no npm, yarn, or pnpm.
- Backward-compatible migrations. Generate them with
bun run db:generateand commit the SQL plusdrizzle/meta. There are no down migrations, so split breaking schema changes into expand and contract steps across deploys.
Adding a slash command
- Create a file in
apps/discord/src/commands/that exportsslashCommand(aSlashCommandBuilder),execute(client, interaction)andexport default { slashCommand, execute }. Handlers receive aChatInputCommandInteraction; the router has already narrowed it. - Add the command to both lists in
apps/discord/src/events/commandRegistry.ts:commandRegistryroutes the interaction andslashCommandsregisters it with Discord (ready.tspushes that list). A unit test fails if the two disagree. - For a new subcommand of
/admin,/owneror/setup, add an entry to that group's route Map (adminRoutes,ownerRoutesorsetupRoutes) instead. - Update the text in
apps/discord/src/commands/help.ts, the command tables inREADME.md, and the command reference.
Branches
| Branch | Role |
|---|---|
main | Production |
dev | Development integration |
FLUFF-{n}-... | Feature branches |
Before you open a PR
Run the same checks CI does:
bun run lint:check
bun run typecheck
bun run test:coverageUse these scripts rather than a bare bun test at the repository root, which
also picks up the end-to-end suites and skips the unit-test environment
fixture. See Testing for test conventions.
CI also runs bun audit, the bot and browser end-to-end suites, a schema drift
check (bun run db:generate must produce no new migration), the docs contrast
check, bun run brand:verify (needs ffmpeg/ffprobe), and a Docker build
that applies the migrations twice. Root bun run test runs the bot unit suite
only.
Green across the board? Open the PR against dev (or main for hotfixes) and
describe the change. Thanks for helping FluffBoost spread a little more
paw-sitivity. 🐾