Thank you for your interest in contributing to TitanBot! This guide covers local setup, project conventions, and what we look for in pull requests.
- Bug fixes and reliability improvements
- New commands or enhancements to existing features
- Documentation updates
Before starting large features, open an issue or discuss in the support server so we can align on scope and avoid duplicate work.
- Node.js 20+ (Docker and CI use Node 20)
- PostgreSQL (recommended for development; the bot can fall back to in-memory storage if PostgreSQL is unavailable)
- A Discord bot application with the intents listed in README.md
- Fork and clone the repository.
- Install dependencies:
npm install
- Copy the environment file and configure it:
At minimum, set
cp .env.example .env
DISCORD_TOKEN,CLIENT_ID, andGUILD_IDfor single-server development. See README.md for full configuration options. - Verify your database setup (when using PostgreSQL):
npm run migrate:check
- Start the bot:
npm start
For Docker-based setup, see README.md.
- Fork the repository and create a branch from
main. - Make focused changes — one logical change per pull request when possible.
- Open a pull request with a clear description of what changed and why.
Use descriptive branch names, for example:
fix/ticket-panel-refreshfeat/economy-shop-filterdocs/contributing-guide
TitanBot uses PostgreSQL as its primary store. If PostgreSQL is unreachable at startup, the bot can operate in a degraded in-memory mode — but that mode is not suitable for production and should not be the only way you test persistence-related changes.
Useful commands:
| Command | Purpose |
|---|---|
npm run migrate |
Apply migrations |
npm run migrate:check |
Verify schema version matches expectations |
npm run migrate:status |
Show current migration status |
If your change modifies the database schema, update the expected schema version in .env.example (SCHEMA_VERSION, SCHEMA_VERSION_LABEL) and ensure npm run migrate:check passes locally.
Test features that read or write guild data with both PostgreSQL and the memory fallback when feasible.
- Match existing style — ES modules (
import/export), async/await, and the conventions used in neighboring files. - Handle errors gracefully — catch failures, log with context, and send user-friendly embed replies where appropriate.
- Avoid breaking guild isolation — guild-specific config and data must stay scoped per server (
guild:{guildId}:...keys,interaction.guildId). - Keep changes minimal — prefer extending existing utilities and services over duplicating logic.
- Document user-facing behavior — update README.md when setup steps or configuration change; mention new env vars in
.env.example.
There is no ESLint config in this repo today; consistency with surrounding code is the main bar.
In your PR description, include:
- What changed
- Why the change is needed
- How to test it manually (commands, config, or env vars to set)
When reporting a bug, include:
- Steps to reproduce
- Expected vs. actual behavior
- Relevant logs (
LOG_LEVEL=debugcan help locally) - Whether you use PostgreSQL or memory fallback
- Bot version / commit hash if known
By contributing, you agree that your contributions will be licensed under the same MIT License that covers this project.