Routing
How file paths become Discord command names and component customIds.
djs-core uses file-based routing: drop a .ts file in the right folder and the framework registers it. No manual imports, no index files.
Folder depth becomes dot-separated routes — admin/moderation/ban.ts → route admin.moderation.ban.
Slash commands
Folder: src/interactions/commands/
| File | Discord command |
|---|---|
ping.ts |
/ping |
admin/kick.ts |
/admin kick |
shop/buy.ts |
/shop buy |
admin/moderation/ban.ts |
/admin moderation ban |
Subdirectories become subcommand groups automatically. The file name is always the leaf command.
src/interactions/commands/├── ping.ts → /ping└── admin/ ├── kick.ts → /admin kick └── moderation/ └── ban.ts → /admin moderation banCommand names come from the file path, not the class name. Rename the file to rename the command.
Context menus
Folder: src/interactions/contexts/
Same dot routing as commands. The leaf segment becomes the context menu name shown in Discord.
| File | Route | Menu name |
|---|---|---|
user/hi.ts |
user.hi |
hi |
message/delete.ts |
message.delete |
delete |
Organize with user/ and message/ subfolders, then set the type with .withType(ApplicationCommandType.User | Message).
Components (buttons, modals, selects)
Folders: src/components/buttons/, modals/, selects/
The route becomes the component customId. djs-core sets it at load time — do not call .setCustomId() in handler files.
| File | customId |
|---|---|
buttons/confirm.ts |
confirm |
buttons/shop/buy.ts |
shop.buy |
modals/feedback.ts |
feedback |
selects/string/pick-color.ts |
string.pick-color |
Select menus can live in type subfolders (string/, user/, role/, channel/, mentionable/) — the full path is part of the id.
Passing per-use data
Routes identify which handler runs. For per-click context (user id, action type), use .withData<T>() on the component and .setData() when sending it:
confirmButton.setData({ userId: target.id, action: "ban" });Data is stored server-side with an optional TTL. Expired interactions get an automatic ephemeral error.
Events
Folder: src/events/
Flat files only — no subfolders. The file stem is the internal listener id.
| File | Listener id |
|---|---|
ready.ts |
ready |
messageCreate.ts |
messageCreate |
Cron tasks
Folder: src/cron/ (requires experimental.cron: true)
Same flat layout as events.
| File | Task id |
|---|---|
hourly-cleanup.ts |
hourly-cleanup |
Inspecting routes
djs-core listPrints every command, context menu, button, select, modal, event, and cron task with its route and source file.
Testing routes
Exercise handler routing in tests with viaHandler and route:
await testCommand(myCommand, { viaHandler: true, route: "admin.moderation.ban",});See Testing.
Keep folder names lowercase and URL-safe. Routes use dots, not slashes — shop/buy.ts is shop.buy, not shop/buy.