diff --git a/apps/website/docs/guide/01-getting-started/02-setup-commandkit.mdx b/apps/website/docs/guide/01-getting-started/02-setup-commandkit.mdx
index e5289cda..c55bd35a 100644
--- a/apps/website/docs/guide/01-getting-started/02-setup-commandkit.mdx
+++ b/apps/website/docs/guide/01-getting-started/02-setup-commandkit.mdx
@@ -3,6 +3,9 @@ title: Setup CommandKit
description: Setup a new CommandKit project using the create-commandkit CLI
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
:::info
- CommandKit requires at least [Node.js](https://nodejs.org/) v24
@@ -52,18 +55,38 @@ The `src/app.ts` file is the main entry point for your application.
This file default exports the discord.js client instance which
CommandKit loads at runtime.
-```ts title="src/app.ts"
-import { Client } from 'discord.js';
+
+
+ ```ts title="src/app.ts"
+ import { Client } from 'discord.js';
-const client = new Client({
- intents: ['Guilds', 'GuildMessages', 'MessageContent'],
-});
+ const client = new Client({
+ intents: ['Guilds', 'GuildMessages', 'MessageContent'],
+ });
-// Optional: Setting up the token manually
-client.token = process.env.MY_BOT_TOKEN;
+ // Optional: Setting up the token manually
+ client.token = process.env.MY_BOT_TOKEN;
-export default client;
-```
+ export default client;
+ ```
+
+
+
+ ```js title="src/app.js"
+ import { Client } from 'discord.js';
+
+ const client = new Client({
+ intents: ['Guilds', 'GuildMessages', 'MessageContent'],
+ });
+
+ // Optional: Setting up the token manually
+ client.token = process.env.MY_BOT_TOKEN;
+
+ export default client;
+ ```
+
+
+
Notice how there's no `client.login()` in this file. This is because
CommandKit will automatically handle the login process for you when
diff --git a/apps/website/docs/guide/02-commands/01-chat-input-commands.mdx b/apps/website/docs/guide/02-commands/01-chat-input-commands.mdx
index 7f4bb3ae..e601d1bc 100644
--- a/apps/website/docs/guide/02-commands/01-chat-input-commands.mdx
+++ b/apps/website/docs/guide/02-commands/01-chat-input-commands.mdx
@@ -2,6 +2,9 @@
title: Chat Input Commands
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Chat input commands, more commonly known as 'Slash Commands', are a
way for users on Discord to perform actions using your bot.
@@ -14,18 +17,43 @@ To create a new chat input command, create a new file in the
will create a basic ping command which will respond with "Pong!" when
executed.
-```ts title="src/app/commands/ping.ts"
-import type { CommandData, ChatInputCommand } from 'commandkit';
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import type { CommandData, ChatInputCommand } from 'commandkit';
+
+ export const command: CommandData = {
+ name: 'ping',
+ description: 'Replies with Pong!',
+ };
+
+ export const chatInput: ChatInputCommand = async (ctx) => {
+ await ctx.interaction.reply('Pong!');
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').ChatInputCommand} ChatInputCommand
+ */
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'ping',
+ description: 'Replies with Pong!',
+ };
-export const command: CommandData = {
- name: 'ping',
- description: 'Replies with Pong!',
-};
+ /** @type {ChatInputCommand} */
+ export const chatInput = async (ctx) => {
+ await ctx.interaction.reply('Pong!');
+ };
+ ```
-export const chatInput: ChatInputCommand = async (ctx) => {
- await ctx.interaction.reply('Pong!');
-};
-```
+
+
## Exports explained
diff --git a/apps/website/docs/guide/02-commands/02-command-options-autocomplete.mdx b/apps/website/docs/guide/02-commands/02-command-options-autocomplete.mdx
index 259f1689..364e70ee 100644
--- a/apps/website/docs/guide/02-commands/02-command-options-autocomplete.mdx
+++ b/apps/website/docs/guide/02-commands/02-command-options-autocomplete.mdx
@@ -2,6 +2,9 @@
title: Options Autocomplete
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
:::warning
This feature is only available for
@@ -24,61 +27,131 @@ and managing your own `interactionCreate` event listener.
To begin, export the `autocomplete` function from the command where
you have an option with `autocomplete` set to `true`.
-```ts title="src/app/commands/pet.ts"
-import type { CommandData, AutocompleteCommand } from 'commandkit';
-import { ApplicationCommandOptionType } from 'discord.js';
-
-export const command: CommandData = {
- name: 'pet',
- description: 'Check in one of your pets.',
- options: [
- {
- name: 'name',
- description: 'The name of your pet',
- type: ApplicationCommandOptionType.String,
- autocomplete: true,
- required: true,
- },
- ],
-};
-
-const pets = Array.from({ length: 20 }, (_, i) => ({
- name: `Pet ${i + 1}`, // e.g. Pet 1, Pet 2, Pet 3, etc.
- value: `petId_${i}`,
-}));
-
-export const autocomplete: AutocompleteCommand = async ({ interaction }) => {
- try {
- // Get the input value of your autocomplete option
- const input = interaction.options.getString('name', false);
- if (!input) {
- interaction.respond(pets);
- return;
- }
-
- const filteredPets = pets.filter((pet) =>
- pet.name.toLowerCase().includes(input.toLowerCase()),
- );
-
- // Respond with what you think the user may trying to find
- interaction.respond(filteredPets);
- } catch (error) {
- console.error('Autocomplete error', error);
- }
-};
-
-export const chatInput: ChatInputCommand = async ({ interaction }) => {
- const chosenPetId = interaction.options.getString('name', true);
- const chosenPet = pets.find((pet) => pet.value === chosenPetId);
-
- if (!chosenPet) {
- interaction.reply('Pet not found.');
- return;
- }
-
- interaction.reply(`You chose ${chosenPet.name}`);
-};
-```
+
+
+ ```ts title="src/app/commands/pet.ts"
+ import type { CommandData, AutocompleteCommand, ChatInputCommand } from 'commandkit';
+ import { ApplicationCommandOptionType } from 'discord.js';
+
+ export const command: CommandData = {
+ name: 'pet',
+ description: 'Check in one of your pets.',
+ options: [
+ {
+ name: 'name',
+ description: 'The name of your pet',
+ type: ApplicationCommandOptionType.String,
+ autocomplete: true,
+ required: true,
+ },
+ ],
+ };
+
+ const pets = Array.from({ length: 20 }, (_, i) => ({
+ name: `Pet ${i + 1}`, // e.g. Pet 1, Pet 2, Pet 3, etc.
+ value: `petId_${i}`,
+ }));
+
+ export const autocomplete: AutocompleteCommand = async ({ interaction }) => {
+ try {
+ // Get the input value of your autocomplete option
+ const input = interaction.options.getString('name', false);
+ if (!input) {
+ interaction.respond(pets);
+ return;
+ }
+
+ const filteredPets = pets.filter((pet) =>
+ pet.name.toLowerCase().includes(input.toLowerCase()),
+ );
+
+ // Respond with what you think the user may trying to find
+ interaction.respond(filteredPets);
+ } catch (error) {
+ console.error('Autocomplete error', error);
+ }
+ };
+
+ export const chatInput: ChatInputCommand = async ({ interaction }) => {
+ const chosenPetId = interaction.options.getString('name', true);
+ const chosenPet = pets.find((pet) => pet.value === chosenPetId);
+
+ if (!chosenPet) {
+ interaction.reply('Pet not found.');
+ return;
+ }
+
+ interaction.reply(`You chose ${chosenPet.name}`);
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/pet.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').AutocompleteCommand} AutocompleteCommand
+ * @typedef {import('commandkit').ChatInputCommand} ChatInputCommand
+ */
+ import { ApplicationCommandOptionType } from 'discord.js';
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'pet',
+ description: 'Check in one of your pets.',
+ options: [
+ {
+ name: 'name',
+ description: 'The name of your pet',
+ type: ApplicationCommandOptionType.String,
+ autocomplete: true,
+ required: true,
+ },
+ ],
+ };
+
+ const pets = Array.from({ length: 20 }, (_, i) => ({
+ name: `Pet ${i + 1}`, // e.g. Pet 1, Pet 2, Pet 3, etc.
+ value: `petId_${i}`,
+ }));
+
+ /** @type {AutocompleteCommand} */
+ export const autocomplete = async ({ interaction }) => {
+ try {
+ // Get the input value of your autocomplete option
+ const input = interaction.options.getString('name', false);
+ if (!input) {
+ interaction.respond(pets);
+ return;
+ }
+
+ const filteredPets = pets.filter((pet) =>
+ pet.name.toLowerCase().includes(input.toLowerCase()),
+ );
+
+ // Respond with what you think the user may trying to find
+ interaction.respond(filteredPets);
+ } catch (error) {
+ console.error('Autocomplete error', error);
+ }
+ };
+
+ /** @type {ChatInputCommand} */
+ export const chatInput = async ({ interaction }) => {
+ const chosenPetId = interaction.options.getString('name', true);
+ const chosenPet = pets.find((pet) => pet.value === chosenPetId);
+
+ if (!chosenPet) {
+ interaction.reply('Pet not found.');
+ return;
+ }
+
+ interaction.reply(`You chose ${chosenPet.name}`);
+ };
+ ```
+
+
+
:::warning
diff --git a/apps/website/docs/guide/02-commands/03-context-menu-commands.mdx b/apps/website/docs/guide/02-commands/03-context-menu-commands.mdx
index 9194aad0..6b86396f 100644
--- a/apps/website/docs/guide/02-commands/03-context-menu-commands.mdx
+++ b/apps/website/docs/guide/02-commands/03-context-menu-commands.mdx
@@ -2,6 +2,9 @@
title: Context Menu Commands
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Context menu commands allows users on Discord to run commands by
either referencing a message or a user. Context menu commands can be
grouped to either 'Message' or 'User' context menu commands.
@@ -19,28 +22,61 @@ understanding the nature of these context menu commands easier.
## Message context menu command
-```ts title="src/app/commands/report-message.ts"
-import type { CommandData, MessageContextMenuCommand } from 'commandkit';
-import { MessageFlags } from 'discord.js';
-
-export const command: CommandData = {
- name: 'report-message',
- description: 'Report a message to moderators.',
-};
-
-export const messageContextMenu: MessageContextMenuCommand = async ({
- interaction,
-}) => {
- const content = interaction.targetMessage.content;
-
- // you could add your message reporting logic here
-
- await interaction.reply({
- content: `You have reported the following message: ${content}`,
- flags: MessageFlags.Ephemeral,
- });
-};
-```
+
+
+ ```ts title="src/app/commands/report-message.ts"
+ import type { CommandData, MessageContextMenuCommand } from 'commandkit';
+ import { MessageFlags } from 'discord.js';
+
+ export const command: CommandData = {
+ name: 'report-message',
+ description: 'Report a message to moderators.',
+ };
+
+ export const messageContextMenu: MessageContextMenuCommand = async ({
+ interaction,
+ }) => {
+ const content = interaction.targetMessage.content;
+
+ // you could add your message reporting logic here
+
+ await interaction.reply({
+ content: `You have reported the following message: ${content}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/report-message.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').MessageContextMenuCommand} MessageContextMenuCommand
+ */
+ import { MessageFlags } from 'discord.js';
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'report-message',
+ description: 'Report a message to moderators.',
+ };
+
+ /** @type {MessageContextMenuCommand} */
+ export const messageContextMenu = async ({ interaction }) => {
+ const content = interaction.targetMessage.content;
+
+ // you could add your message reporting logic here
+
+ await interaction.reply({
+ content: `You have reported the following message: ${content}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ };
+ ```
+
+
+
By just exporting the `messageContextMenu` function from your command
file, CommandKit will properly update your command type before
@@ -53,25 +89,58 @@ handlers.
The logic for registering and handling user context menu commands is
very similar to message context menu commands.
-```ts title="src/app/commands/report-user.ts"
-import type { CommandData, UserContextMenuCommand } from 'commandkit';
-import { MessageFlags } from 'discord.js';
-
-export const command: CommandData = {
- name: 'report-user',
- description: 'Report a user to moderators.',
-};
-
-export const userContextMenu: UserContextMenuCommand = async ({
- interaction,
-}) => {
- const userId = interaction.targetUser.id;
-
- // you could add your user reporting logic here
-
- await interaction.reply({
- content: `You have reported a user with the ID: ${userId}`,
- flags: MessageFlags.Ephemeral,
- });
-};
-```
+
+
+ ```ts title="src/app/commands/report-user.ts"
+ import type { CommandData, UserContextMenuCommand } from 'commandkit';
+ import { MessageFlags } from 'discord.js';
+
+ export const command: CommandData = {
+ name: 'report-user',
+ description: 'Report a user to moderators.',
+ };
+
+ export const userContextMenu: UserContextMenuCommand = async ({
+ interaction,
+ }) => {
+ const userId = interaction.targetUser.id;
+
+ // you could add your user reporting logic here
+
+ await interaction.reply({
+ content: `You have reported a user with the ID: ${userId}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/report-user.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').UserContextMenuCommand} UserContextMenuCommand
+ */
+ import { MessageFlags } from 'discord.js';
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'report-user',
+ description: 'Report a user to moderators.',
+ };
+
+ /** @type {UserContextMenuCommand} */
+ export const userContextMenu = async ({ interaction }) => {
+ const userId = interaction.targetUser.id;
+
+ // you could add your user reporting logic here
+
+ await interaction.reply({
+ content: `You have reported a user with the ID: ${userId}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ };
+ ```
+
+
+
diff --git a/apps/website/docs/guide/02-commands/04-message-commands.mdx b/apps/website/docs/guide/02-commands/04-message-commands.mdx
index b3c6b233..3a47f9c6 100644
--- a/apps/website/docs/guide/02-commands/04-message-commands.mdx
+++ b/apps/website/docs/guide/02-commands/04-message-commands.mdx
@@ -2,6 +2,9 @@
title: Message Commands
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Message commands, which are generally considered 'Legacy', are a way
to run commands on Discord bots using regular messages. Before the
introduction of
@@ -25,17 +28,41 @@ Message commands, like all the other command types, live in your
message command, just export the `message` function from your command
file.
-```ts title="src/app/commands/ping.ts"
-import type { CommandData, MessageCommand } from 'commandkit';
-
-export const command: CommandData = {
- name: 'ping',
-};
-
-export const message: MessageCommand = async (ctx) => {
- await ctx.message.reply('Pong!');
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import type { CommandData, MessageCommand } from 'commandkit';
+
+ export const command: CommandData = {
+ name: 'ping',
+ };
+
+ export const message: MessageCommand = async (ctx) => {
+ await ctx.message.reply('Pong!');
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').MessageCommand} MessageCommand
+ */
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'ping',
+ };
+
+ /** @type {MessageCommand} */
+ export const message = async (ctx) => {
+ await ctx.message.reply('Pong!');
+ };
+ ```
+
+
+
## Message command options (arguments)
@@ -45,17 +72,41 @@ idea of message command options will be different compared to
getting parsed data, you'll essentially be dealing with string
'arguments'.
-```ts title="src/app/commands/ping.ts" {8}
-import type { CommandData, MessageCommand } from 'commandkit';
-
-export const command: CommandData = {
- name: 'ping',
-};
-
-export const message: MessageCommand = async (ctx) => {
- const args = ctx.args(); // string[]
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts" {8}
+ import type { CommandData, MessageCommand } from 'commandkit';
+
+ export const command: CommandData = {
+ name: 'ping',
+ };
+
+ export const message: MessageCommand = async (ctx) => {
+ const args = ctx.args(); // string[]
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js" {13}
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').MessageCommand} MessageCommand
+ */
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'ping',
+ };
+
+ /** @type {MessageCommand} */
+ export const message = async (ctx) => {
+ const args = ctx.args(); // string[]
+ };
+ ```
+
+
+
With the above command as an example, if a user on Discord runs
`!ping john jack jane`, the value of `args` will equal
@@ -66,13 +117,28 @@ With the above command as an example, if a user on Discord runs
The simplest way to set a custom prefix is using the
`setPrefixResolver` method on the `commandkit` instance:
-```ts title="src/app.ts"
-import { commandkit } from 'commandkit';
+
+
+ ```ts title="src/app.ts"
+ import { commandkit } from 'commandkit';
-commandkit.setPrefixResolver(async (message) => {
- return '?';
-});
-```
+ commandkit.setPrefixResolver(async (message) => {
+ return '?';
+ });
+ ```
+
+
+
+ ```js title="src/app.js"
+ import { commandkit } from 'commandkit';
+
+ commandkit.setPrefixResolver(async (message) => {
+ return '?';
+ });
+ ```
+
+
+
This sets a global prefix of `?` for all message commands. Your bot
will now respond to commands like `?help` or `?ping`.
@@ -82,7 +148,7 @@ will now respond to commands like `?help` or `?ping`.
You can return an array of strings to support multiple prefixes
simultaneously:
-```ts
+```js
return ['?', '!', '>'];
```
@@ -93,27 +159,56 @@ return ['?', '!', '>'];
For a more dynamic approach, you might want different prefixes for
different guilds. Here's how to implement that:
-```ts title="src/app.ts"
-import { commandkit } from 'commandkit';
-import { database } from '../database'; // This is a mock database
-
-commandkit.setPrefixResolver(async (message) => {
- if (!message.guildId) {
- return '!'; // Fallback to '!' if command is used in a DM
- }
-
- const guildSettings = await database.findUnique({
- where: {
- guildId: message.guildId,
- },
- select: {
- prefix: true,
- },
- });
-
- return guildSettings?.prefix ?? '!'; // Fallback to '!' if no prefix is found
-});
-```
+
+
+ ```ts title="src/app.ts"
+ import { commandkit } from 'commandkit';
+ import { database } from '../database'; // This is a mock database
+
+ commandkit.setPrefixResolver(async (message) => {
+ if (!message.guildId) {
+ return '!'; // Fallback to '!' if command is used in a DM
+ }
+
+ const guildSettings = await database.findUnique({
+ where: {
+ guildId: message.guildId,
+ },
+ select: {
+ prefix: true,
+ },
+ });
+
+ return guildSettings?.prefix ?? '!'; // Fallback to '!' if no prefix is found
+ });
+ ```
+
+
+
+ ```js title="src/app.js"
+ import { commandkit } from 'commandkit';
+ import { database } from '../database'; // This is a mock database
+
+ commandkit.setPrefixResolver(async (message) => {
+ if (!message.guildId) {
+ return '!'; // Fallback to '!' if command is used in a DM
+ }
+
+ const guildSettings = await database.findUnique({
+ where: {
+ guildId: message.guildId,
+ },
+ select: {
+ prefix: true,
+ },
+ });
+
+ return guildSettings?.prefix ?? '!'; // Fallback to '!' if no prefix is found
+ });
+ ```
+
+
+
:::warning
diff --git a/apps/website/docs/guide/02-commands/05-command-metadata.mdx b/apps/website/docs/guide/02-commands/05-command-metadata.mdx
index b941c5db..5caa02f8 100644
--- a/apps/website/docs/guide/02-commands/05-command-metadata.mdx
+++ b/apps/website/docs/guide/02-commands/05-command-metadata.mdx
@@ -2,23 +2,51 @@
title: Command Metadata
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Command metadata is a way to add additional information to your
commands that CommandKit will handle.
To get started, you can export a `metadata` object from your command:
-```ts title="src/app/commands/ping.ts" {8-10}
-import type { CommandData, CommandMetadata } from 'commandkit';
-
-export const command: CommandData = {
- name: 'ping',
- description: 'Replies with Pong!',
-};
-
-export const metadata: CommandMetadata = {
- // Add your metadata here
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts" {8-10}
+ import type { CommandData, CommandMetadata } from 'commandkit';
+
+ export const command: CommandData = {
+ name: 'ping',
+ description: 'Replies with Pong!',
+ };
+
+ export const metadata: CommandMetadata = {
+ // Add your metadata here
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js" {13-15}
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').CommandMetadata} CommandMetadata
+ */
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'ping',
+ description: 'Replies with Pong!',
+ };
+
+ /** @type {CommandMetadata} */
+ export const metadata = {
+ // Add your metadata here
+ };
+ ```
+
+
+
## Metadata properties
@@ -27,12 +55,25 @@ export const metadata: CommandMetadata = {
This is a string, or array of user permission strings that will be
required by the person executing the command.
-```ts title="src/app/commands/ping.ts"
-export const metadata: CommandMetadata = {
- // If the user does not have the Administrator permission, CommandKit will let them know
- userPermissions: 'Administrator',
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ export const metadata: CommandMetadata = {
+ // If the user does not have the Administrator permission, CommandKit will let them know
+ userPermissions: 'Administrator',
+ };
+ ```
+
+
+ ```js title="src/app/commands/ping.js"
+ /** @type {CommandMetadata} */
+ export const metadata = {
+ // If the user does not have the Administrator permission, CommandKit will let them know
+ userPermissions: 'Administrator',
+ };
+ ```
+
+
### `botPermissions`
@@ -41,23 +82,48 @@ required by your bot to execute the command. This is useful for
commands where your bot needs to have certain permissions in a guild
e.g. moderation commands.
-```ts title="src/app/commands/ping.ts"
-export const metadata: CommandMetadata = {
- // If the bot does not have these permissions, CommandKit will let them know
- botPermissions: ['KickMembers', 'BanMembers'],
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ export const metadata: CommandMetadata = {
+ // If the bot does not have these permissions, CommandKit will let them know
+ botPermissions: ['KickMembers', 'BanMembers'],
+ };
+ ```
+
+
+ ```js title="src/app/commands/ping.js"
+ /** @type {CommandMetadata} */
+ export const metadata = {
+ // If the bot does not have these permissions, CommandKit will let them know
+ botPermissions: ['KickMembers', 'BanMembers'],
+ };
+ ```
+
+
### `guilds`
This is an array of guild IDs that the command will be registered in,
or be available to be executed (message commands).
-```ts title="src/app/commands/ping.ts"
-export const metadata: CommandMetadata = {
- guilds: ['1234567890', '1234567891'],
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ export const metadata: CommandMetadata = {
+ guilds: ['1234567890', '1234567891'],
+ };
+ ```
+
+
+ ```js title="src/app/commands/ping.js"
+ /** @type {CommandMetadata} */
+ export const metadata = {
+ guilds: ['1234567890', '1234567891'],
+ };
+ ```
+
+
### `aliases`
@@ -70,11 +136,23 @@ This only works for [message commands](./04-message-commands.mdx).
:::
-```ts title="src/app/commands/ping.ts"
-export const metadata: CommandMetadata = {
- aliases: ['p', 'pong'],
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ export const metadata: CommandMetadata = {
+ aliases: ['p', 'pong'],
+ };
+ ```
+
+
+ ```js title="src/app/commands/ping.js"
+ /** @type {CommandMetadata} */
+ export const metadata = {
+ aliases: ['p', 'pong'],
+ };
+ ```
+
+
## Generated metadata
@@ -82,17 +160,42 @@ If you'd like to generate metadata dynamically, you can export a
`generateMetadata` function from your command file that should return
a `CommandMetadata` object.
-```ts title="src/app/commands/ping.ts"
-import type { CommandMetadataFunction } from 'commandkit';
-
-export const generateMetadata: CommandMetadataFunction = async () => {
- // Dynamically determine the metadata for the command
-
- return {
- userPermissions: 'Administrator',
- botPermissions: ['KickMembers', 'BanMembers'],
- guilds: ['1234567890', '1234567891'],
- aliases: ['p', 'pong'],
- };
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import type { CommandMetadataFunction } from 'commandkit';
+
+ export const generateMetadata: CommandMetadataFunction = async () => {
+ // Dynamically determine the metadata for the command
+
+ return {
+ userPermissions: 'Administrator',
+ botPermissions: ['KickMembers', 'BanMembers'],
+ guilds: ['1234567890', '1234567891'],
+ aliases: ['p', 'pong'],
+ };
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').CommandMetadataFunction} CommandMetadataFunction
+ */
+
+ /** @type {CommandMetadataFunction} */
+ export const generateMetadata = async () => {
+ // Dynamically determine the metadata for the command
+
+ return {
+ userPermissions: 'Administrator',
+ botPermissions: ['KickMembers', 'BanMembers'],
+ guilds: ['1234567890', '1234567891'],
+ aliases: ['p', 'pong'],
+ };
+ };
+ ```
+
+
+
diff --git a/apps/website/docs/guide/02-commands/06-after-function.mdx b/apps/website/docs/guide/02-commands/06-after-function.mdx
index 210a872d..7cbff4da 100644
--- a/apps/website/docs/guide/02-commands/06-after-function.mdx
+++ b/apps/website/docs/guide/02-commands/06-after-function.mdx
@@ -2,6 +2,9 @@
title: after Function
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
:::warning UNSTABLE
The `after()` function is currently marked as unstable and may change
@@ -16,28 +19,60 @@ cleanup tasks.
## Usage
-```ts title="src/app/commands/ping.ts"
-import {
- type CommandData,
- type ChatInputCommand,
- unstable_after as after,
-} from 'commandkit';
-
-export const command: CommandData = {};
-
-export const chatInput: ChatInputCommand = async (ctx) => {
- after(() => {
- // This code will be executed after the command has been executed
- // Perform any cleanup here
- console.log('Command has been executed');
- });
-
- await ctx.interaction.reply({
- content: 'Hello World',
- ephemeral: true,
- });
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import {
+ type CommandData,
+ type ChatInputCommand,
+ unstable_after as after,
+ } from 'commandkit';
+
+ export const command: CommandData = {};
+
+ export const chatInput: ChatInputCommand = async (ctx) => {
+ after(() => {
+ // This code will be executed after the command has been executed
+ // Perform any cleanup here
+ console.log('Command has been executed');
+ });
+
+ await ctx.interaction.reply({
+ content: 'Hello World',
+ ephemeral: true,
+ });
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').ChatInputCommand} ChatInputCommand
+ */
+ import { unstable_after as after } from 'commandkit';
+
+ /** @type {CommandData} */
+ export const command = {};
+
+ /** @type {ChatInputCommand} */
+ export const chatInput = async (ctx) => {
+ after(() => {
+ // This code will be executed after the command has been executed
+ // Perform any cleanup here
+ console.log('Command has been executed');
+ });
+
+ await ctx.interaction.reply({
+ content: 'Hello World',
+ ephemeral: true,
+ });
+ };
+ ```
+
+
+
:::info
@@ -51,19 +86,47 @@ the command execution was successful or not.
You can cancel the after function by calling the `cancelAfter`
function with the ID of the after function.
-```ts title="src/app/commands/ping.ts"
-import {
- unstable_after as after,
- unstable_cancelAfter as cancelAfter,
-} from 'commandkit';
-
-export const chatInput: ChatInputCommand = async (ctx) => {
- const id = after(() => {
- console.log('This will run after the command has finished executing.');
- });
-
- if (something) {
- cancelAfter(id);
- }
-};
-```
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import {
+ unstable_after as after,
+ unstable_cancelAfter as cancelAfter,
+ } from 'commandkit';
+
+ export const chatInput: ChatInputCommand = async (ctx) => {
+ const id = after(() => {
+ console.log('This will run after the command has finished executing.');
+ });
+
+ if (something) {
+ cancelAfter(id);
+ }
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').ChatInputCommand} ChatInputCommand
+ */
+ import {
+ unstable_after as after,
+ unstable_cancelAfter as cancelAfter,
+ } from 'commandkit';
+
+ /** @type {ChatInputCommand} */
+ export const chatInput = async (ctx) => {
+ const id = after(() => {
+ console.log('This will run after the command has finished executing.');
+ });
+
+ if (something) {
+ cancelAfter(id);
+ }
+ };
+ ```
+
+
+
diff --git a/apps/website/docs/guide/02-commands/08-middlewares.mdx b/apps/website/docs/guide/02-commands/08-middlewares.mdx
index c67bbe3a..0a7f8d33 100644
--- a/apps/website/docs/guide/02-commands/08-middlewares.mdx
+++ b/apps/website/docs/guide/02-commands/08-middlewares.mdx
@@ -2,6 +2,9 @@
title: Middlewares
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Middlewares in CommandKit allow you to execute code before and after
command execution. This is incredibly powerful for implementing
features like logging, authentication, permission checks, or any other
@@ -16,41 +19,101 @@ All middleware files follow the same export pattern. You can export
`beforeExecute` and `afterExecute` functions that will run at their
respective times during command execution.
-```ts title="src/app/commands/+middleware.ts"
-import { MiddlewareContext } from 'commandkit';
+
+
+ ```ts title="src/app/commands/+middleware.ts"
+ import { MiddlewareContext } from 'commandkit';
+
+ export function beforeExecute(ctx: MiddlewareContext) {
+ // This function will be executed before the command is executed
+ console.log(`User ${ctx.interaction.user.id} is about to execute a command`);
+ }
-export function beforeExecute(ctx: MiddlewareContext) {
- // This function will be executed before the command is executed
- console.log(`User ${ctx.interaction.user.id} is about to execute a command`);
-}
+ export function afterExecute(ctx: MiddlewareContext) {
+ // This function will be executed after the command is executed
+ console.log(
+ `Command execution completed for user ${ctx.interaction.user.id}`,
+ );
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/+middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * Executed before command execution
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ // This function will be executed before the command is executed
+ console.log(`User ${ctx.interaction.user.id} is about to execute a command`);
+ }
-export function afterExecute(ctx: MiddlewareContext) {
- // This function will be executed after the command is executed
- console.log(
- `Command execution completed for user ${ctx.interaction.user.id}`,
- );
-}
-```
+ /**
+ * Executed after command execution
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function afterExecute(ctx) {
+ // This function will be executed after the command is executed
+ console.log(
+ `Command execution completed for user ${ctx.interaction.user.id}`,
+ );
+ }
+ ```
+
+
+
## Stop command execution
You can stop a command from running by calling `stopMiddlewares()` in
the `beforeExecute` function.
-```ts title="src/app/commands/+middleware.ts"
-import type { MiddlewareContext } from 'commandkit';
+
+
+ ```ts title="src/app/commands/+middleware.ts"
+ import type { MiddlewareContext } from 'commandkit';
-export function beforeExecute(ctx: MiddlewareContext) {
- if (ctx.interaction.user.id !== '1234567890') {
- // Conditionally stop command execution
- console.log(`${ctx.commandName} will not be executed!`);
- stopMiddlewares();
- }
+ export function beforeExecute(ctx: MiddlewareContext) {
+ if (ctx.interaction.user.id !== '1234567890') {
+ // Conditionally stop command execution
+ console.log(`${ctx.commandName} will not be executed!`);
+ stopMiddlewares();
+ }
- // Continue with command execution
- console.log(`${ctx.commandName} will be executed!`);
-}
-```
+ // Continue with command execution
+ console.log(`${ctx.commandName} will be executed!`);
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/+middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ if (ctx.interaction.user.id !== '1234567890') {
+ // Conditionally stop command execution
+ console.log(`${ctx.commandName} will not be executed!`);
+ stopMiddlewares();
+ }
+
+ // Continue with command execution
+ console.log(`${ctx.commandName} will be executed!`);
+ }
+ ```
+
+
+
:::tip
@@ -72,26 +135,59 @@ If you still want to use `stopMiddlewares()` in a try/catch block, you
can use the `isErrorType` function to check if the error is an
instance of the `CommandKitErrorCodes.StopMiddlewares` error.
-```ts title="src/app/commands/+middleware.ts"
-import type { MiddlewareContext } from 'commandkit';
-
-export function beforeExecute(ctx: MiddlewareContext) {
- try {
- // code that may throw an error
-
- stopMiddlewares(); // conditionally stop the middleware chain
- } catch (error) {
- if (isErrorType(error, CommandKitErrorCodes.StopMiddlewares)) {
- // if stopMiddlewares() is called in the try block, throw it so CommandKit can stop the middleware chain
- throw error;
+
+
+ ```ts title="src/app/commands/+middleware.ts"
+ import type { MiddlewareContext } from 'commandkit';
+
+ export function beforeExecute(ctx: MiddlewareContext) {
+ try {
+ // code that may throw an error
+
+ stopMiddlewares(); // conditionally stop the middleware chain
+ } catch (error) {
+ if (isErrorType(error, CommandKitErrorCodes.StopMiddlewares)) {
+ // if stopMiddlewares() is called in the try block, throw it so CommandKit can stop the middleware chain
+ throw error;
+ }
+
+ // this means that the code threw the error, and stopMiddlewares() was not called
+ // the rest of the middlewares will be executed as normal
+ console.error(error);
+ }
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/+middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ try {
+ // code that may throw an error
+
+ stopMiddlewares(); // conditionally stop the middleware chain
+ } catch (error) {
+ if (isErrorType(error, CommandKitErrorCodes.StopMiddlewares)) {
+ // if stopMiddlewares() is called in the try block, throw it so CommandKit can stop the middleware chain
+ throw error;
+ }
+
+ // this means that the code threw the error, and stopMiddlewares() was not called
+ // the rest of the middlewares will be executed as normal
+ console.error(error);
+ }
}
+ ```
- // this means that the code threw the error, and stopMiddlewares() was not called
- // the rest of the middlewares will be executed as normal
- console.error(error);
- }
-}
-```
+
+
:::
@@ -103,16 +199,39 @@ Create a `+middleware.ts` file in any commands directory to apply
middleware to all commands within that directory and its
subdirectories.
-```ts title="src/app/commands/(Moderation)/+middleware.ts"
-import type { MiddlewareContext } from 'commandkit';
+
+
+ ```ts title="src/app/commands/(Moderation)/+middleware.ts"
+ import type { MiddlewareContext } from 'commandkit';
+
+ export function beforeExecute(ctx: MiddlewareContext) {
+ // This middleware will run before any moderation command
+ if (!ctx.interaction.member.permissions.has('KickMembers')) {
+ throw new Error('You need moderation permissions to use this command');
+ }
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/(Moderation)/+middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ // This middleware will run before any moderation command
+ if (!ctx.interaction.member.permissions.has('KickMembers')) {
+ throw new Error('You need moderation permissions to use this command');
+ }
+ }
+ ```
-export function beforeExecute(ctx: MiddlewareContext) {
- // This middleware will run before any moderation command
- if (!ctx.interaction.member.permissions.has('KickMembers')) {
- throw new Error('You need moderation permissions to use this command');
- }
-}
-```
+
+
### Command-specific middleware
@@ -120,30 +239,74 @@ For command-specific middleware, create a file named
`+.middleware.ts` where `` matches your
command file name.
-```ts title="src/app/commands/+ban.middleware.ts"
-import type { MiddlewareContext } from 'commandkit';
+
+
+ ```ts title="src/app/commands/+ban.middleware.ts"
+ import type { MiddlewareContext } from 'commandkit';
-export function beforeExecute(ctx: MiddlewareContext) {
- // This middleware only runs before the ban command
- console.log('Ban command is about to be executed');
-}
-```
+ export function beforeExecute(ctx: MiddlewareContext) {
+ // This middleware only runs before the ban command
+ console.log('Ban command is about to be executed');
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/+ban.middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ // This middleware only runs before the ban command
+ console.log('Ban command is about to be executed');
+ }
+ ```
+
+
+
### Global middleware
Create a `+global-middleware.ts` file in your commands directory to
apply middleware to every command in your entire Discord bot.
-```ts title="src/app/commands/+global-middleware.ts"
-import type { MiddlewareContext } from 'commandkit';
+
+
+ ```ts title="src/app/commands/+global-middleware.ts"
+ import type { MiddlewareContext } from 'commandkit';
+
+ export function beforeExecute(ctx: MiddlewareContext) {
+ // This middleware runs before ANY command in your bot
+ console.log(
+ `Command executed by ${ctx.interaction.user.tag} in ${ctx.interaction.guild?.name || 'DMs'}`,
+ );
+ }
+ ```
+
+
+
+ ```js title="src/app/commands/+global-middleware.js"
+ /**
+ * @typedef {import('commandkit').MiddlewareContext} MiddlewareContext
+ */
+
+ /**
+ * @param {MiddlewareContext} ctx - The middleware context
+ */
+ export function beforeExecute(ctx) {
+ // This middleware runs before ANY command in your bot
+ console.log(
+ `Command executed by ${ctx.interaction.user.tag} in ${ctx.interaction.guild?.name || 'DMs'}`,
+ );
+ }
+ ```
-export function beforeExecute(ctx: MiddlewareContext) {
- // This middleware runs before ANY command in your bot
- console.log(
- `Command executed by ${ctx.interaction.user.tag} in ${ctx.interaction.guild?.name || 'DMs'}`,
- );
-}
-```
+
+
:::tip
diff --git a/apps/website/docs/guide/03-events/01-discordjs-events.mdx b/apps/website/docs/guide/03-events/01-discordjs-events.mdx
index 5fa1f86b..304faea6 100644
--- a/apps/website/docs/guide/03-events/01-discordjs-events.mdx
+++ b/apps/website/docs/guide/03-events/01-discordjs-events.mdx
@@ -2,6 +2,9 @@
title: Discord.js Events
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
Events allow your Discord bot to react to various actions happening on
Discord, such as when users send messages, join guilds, or when your
bot comes online.
@@ -52,15 +55,35 @@ To create an event handler, create a folder inside the
`src/app/events` directory which should match the event name from
Discord.js. This example will use the `"clientReady"` event.
-```ts title="src/app/events/clientReady/log.ts"
-import type { EventHandler } from 'commandkit';
+
+
+ ```ts title="src/app/events/clientReady/log.ts"
+ import type { EventHandler } from 'commandkit';
-const handler: EventHandler<'clientReady'> = (client) => {
- console.log(`🤖 ${client.user.displayName} is online!`);
-};
+ const handler: EventHandler<'clientReady'> = (client) => {
+ console.log(`🤖 ${client.user.displayName} is online!`);
+ };
-export default handler;
-```
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/clientReady/log.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'clientReady'>} ClientReadyHandler
+ */
+
+ /** @type {ClientReadyHandler} */
+ const handler = (client) => {
+ console.log(`🤖 ${client.user.displayName} is online!`);
+ };
+
+ export default handler;
+ ```
+
+
+
That's it! CommandKit will automatically detect this file and register
it as one of the handler functions for the `"clientReady"` event.
@@ -87,34 +110,78 @@ definition.
You may want to have some events to only get called once. For this,
you can export a variable called `once` from your event function file.
-```ts title="src/app/events/clientReady/log.ts"
-import type { EventHandler } from 'commandkit';
+
+
+ ```ts title="src/app/events/clientReady/log.ts"
+ import type { EventHandler } from 'commandkit';
-export const once = true;
+ export const once = true;
-const handler: EventHandler<'clientReady'> = (client) => {
- console.log(`🤖 ${client.user.displayName} is online!`);
-};
+ const handler: EventHandler<'clientReady'> = (client) => {
+ console.log(`🤖 ${client.user.displayName} is online!`);
+ };
-export default handler;
-```
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/clientReady/log.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'clientReady'>} ClientReadyHandler
+ */
+
+ export const once = true;
+
+ /** @type {ClientReadyHandler} */
+ const handler = (client) => {
+ console.log(`🤖 ${client.user.displayName} is online!`);
+ };
+
+ export default handler;
+ ```
+
+
+
## Events with multiple parameter
Some Discord.js events have multiple parameters, such as the
`"messageUpdate"` event.
-```ts title="src/app/events/messageUpdate/log-message-update.ts"
-import type { EventHandler } from 'commandkit';
+
+
+ ```ts title="src/app/events/messageUpdate/log-message-update.ts"
+ import type { EventHandler } from 'commandkit';
-const handler: EventHandler<'messageUpdate'> = (oldMessage, newMessage) => {
- console.log(
- `Message from ${oldMessage.author?.username} updated: ${oldMessage.content} -> ${newMessage.content}`,
- );
-};
+ const handler: EventHandler<'messageUpdate'> = (oldMessage, newMessage) => {
+ console.log(
+ `Message from ${oldMessage.author?.username} updated: ${oldMessage.content} -> ${newMessage.content}`,
+ );
+ };
-export default handler;
-```
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/messageUpdate/log-message-update.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'messageUpdate'>} MessageUpdateHandler
+ */
+
+ /** @type {MessageUpdateHandler} */
+ const handler = (oldMessage, newMessage) => {
+ console.log(
+ `Message from ${oldMessage.author?.username} updated: ${oldMessage.content} -> ${newMessage.content}`,
+ );
+ };
+
+ export default handler;
+ ```
+
+
+
## Additional parameters
@@ -125,19 +192,39 @@ and
[`CommandKit`](../../api-reference/commandkit/classes/command-kit.mdx)
instance.
-```ts title="src/app/events/messageCreate/log.ts"
-import type { EventHandler } from 'commandkit';
+
+
+ ```ts title="src/app/events/messageCreate/log.ts"
+ import type { EventHandler } from 'commandkit';
-const handler: EventHandler<'messageCreate'> = (
- message,
- client,
- commandkit,
-) => {
- console.log(`Message from ${message.author.username}: ${message.content}`);
-};
+ const handler: EventHandler<'messageCreate'> = (
+ message,
+ client,
+ commandkit,
+ ) => {
+ console.log(`Message from ${message.author.username}: ${message.content}`);
+ };
-export default handler;
-```
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/messageCreate/log.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'messageCreate'>} MessageCreateHandler
+ */
+
+ /** @type {MessageCreateHandler} */
+ const handler = (message, client, commandkit) => {
+ console.log(`Message from ${message.author.username}: ${message.content}`);
+ };
+
+ export default handler;
+ ```
+
+
+
## Multiple handlers for the same event
@@ -149,29 +236,73 @@ is called.
For example, you might want to do several things when a message is
created:
-```ts title="src/app/events/messageCreate/give-xp.ts"
-import type { EventHandler } from 'commandkit';
-
-const handler: EventHandler<'messageCreate'> = (message) => {
- // Don't give XP to bots
- if (message.author.bot) return;
-
- // Give XP to the user
- console.log(`Giving XP to ${message.author.username}`);
-};
-
-export default handler;
-```
-
-```ts title="src/app/events/messageCreate/log-message.ts"
-import type { EventHandler } from 'commandkit';
-
-const handler: EventHandler<'messageCreate'> = (message) => {
- console.log(`Message from ${message.author.username}: ${message.content}`);
-};
-
-export default handler;
-```
+
+
+ ```ts title="src/app/events/messageCreate/give-xp.ts"
+ import type { EventHandler } from 'commandkit';
+
+ const handler: EventHandler<'messageCreate'> = (message) => {
+ // Don't give XP to bots
+ if (message.author.bot) return;
+
+ // Give XP to the user
+ console.log(`Giving XP to ${message.author.username}`);
+ };
+
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/messageCreate/give-xp.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'messageCreate'>} MessageCreateHandler
+ */
+
+ /** @type {MessageCreateHandler} */
+ const handler = (message) => {
+ // Don't give XP to bots
+ if (message.author.bot) return;
+
+ // Give XP to the user
+ console.log(`Giving XP to ${message.author.username}`);
+ };
+
+ export default handler;
+ ```
+
+
+
+
+
+
+ ```ts title="src/app/events/messageCreate/log-message.ts"
+ import type { EventHandler } from 'commandkit';
+
+ const handler: EventHandler<'messageCreate'> = (message) => {
+ console.log(`Message from ${message.author.username}: ${message.content}`);
+ };
+
+ export default handler;
+ ```
+
+
+
+ ```js title="src/app/events/messageCreate/log-message.js"
+ /**
+ * @typedef {import('commandkit').EventHandler<'messageCreate'>} MessageCreateHandler
+ */
+
+ /** @type {MessageCreateHandler} */
+ const handler = (message) => {
+ console.log(`Message from ${message.author.username}: ${message.content}`);
+ };
+
+ export default handler;
+ ```
+
+
+
Both handler functions will be called whenever a message is sent in
Discord.
diff --git a/apps/website/docs/guide/04-jsx-components/01-using-jsx.mdx b/apps/website/docs/guide/04-jsx-components/01-using-jsx.mdx
index 5b832d94..9d6661b7 100644
--- a/apps/website/docs/guide/04-jsx-components/01-using-jsx.mdx
+++ b/apps/website/docs/guide/04-jsx-components/01-using-jsx.mdx
@@ -2,6 +2,9 @@
title: Using JSX
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
CommandKit provides first-class JSX support for both TypeScript and
JavaScript projects. This allows you to write Discord message
components using a familiar and intuitive syntax if you're already
@@ -11,16 +14,30 @@ familiar with React.
CommandKit automatically configures JSX support in your project. If
you are doing a manual setup, ensure you have the following in your
-`tsconfig.json` or `jsconfig.json`:
+configuration:
-```json
-{
- "compilerOptions": {
- "jsx": "react-jsx",
- "jsxImportSource": "commandkit"
- }
-}
-```
+
+
+ ```json title="tsconfig.json"
+ {
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "commandkit"
+ }
+ }
+ ```
+
+
+ ```json title="jsconfig.json"
+ {
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "commandkit"
+ }
+ }
+ ```
+
+
## Available components
@@ -39,38 +56,83 @@ builders:
## Example usage
-```tsx
-import { Container, TextDisplay, ActionRow, Button } from 'commandkit';
-import { ButtonStyle } from 'discord.js';
+
+
+ ```tsx title="example.tsx"
+ import { Container, TextDisplay, ActionRow, Button } from 'commandkit';
+ import { ButtonStyle } from 'discord.js';
+
+ const message = (
+
+ Welcome to our server!
+
+
+
+
+ );
+
+ interaction.reply({
+ components: [message],
+ });
+ ```
+
+
+
+ ```jsx title="example.jsx"
+ import { Container, TextDisplay, ActionRow, Button } from 'commandkit';
+ import { ButtonStyle } from 'discord.js';
+
+ const message = (
+
+ Welcome to our server!
+
+
+
+
+ );
-const message = (
-
- Welcome to our server!
-
-
-
-
-);
+ interaction.reply({
+ components: [message],
+ });
+ ```
-interaction.reply({
- components: [message],
-});
-```
+
+
## JSX fragments
CommandKit fully supports JSX fragments for grouping multiple elements
without adding extra nodes:
-```tsx
-const elements = (
- <>
- First message
- Second message
- >
-);
-
-interaction.reply({
- components: elements,
-});
-```
+
+
+ ```tsx title="fragments.tsx"
+ const elements = (
+ <>
+ First message
+ Second message
+ >
+ );
+
+ interaction.reply({
+ components: elements,
+ });
+ ```
+
+
+
+ ```jsx title="fragments.jsx"
+ const elements = (
+ <>
+ First message
+ Second message
+ >
+ );
+
+ interaction.reply({
+ components: elements,
+ });
+ ```
+
+
+
diff --git a/apps/website/docs/guide/08-advanced/01-setup-commandkit-manually.mdx b/apps/website/docs/guide/08-advanced/01-setup-commandkit-manually.mdx
index 2a86920b..49f4c7b4 100644
--- a/apps/website/docs/guide/08-advanced/01-setup-commandkit-manually.mdx
+++ b/apps/website/docs/guide/08-advanced/01-setup-commandkit-manually.mdx
@@ -29,32 +29,64 @@ npm install commandkit@next
## Configuration file
-To get started, create a file called `commandkit.config.ts` at the
-root of your project. This file is used to configure CommandKit and
-optionally its plugins.
+To get started, create a configuration file at the root of your
+project. This file is used to configure CommandKit and optionally its
+plugins.
-```ts title="commandkit.config.ts"
-import { defineConfig } from 'commandkit';
+
+
+ ```ts title="commandkit.config.ts"
+ import { defineConfig } from 'commandkit';
-export default defineConfig({});
-```
+ export default defineConfig({});
+ ```
+
+
+
+ ```js title="commandkit.config.js"
+ import { defineConfig } from 'commandkit';
+
+ export default defineConfig({});
+ ```
+
+
+
## Entrypoint file
-Then, create a folder called `src`, followed by a file called `app.ts`
-inside it. The file should look like this:
+Then, create a folder called `src`, followed by an app file inside it.
+The file should look like this:
-```ts title="src/app.ts"
-import { Client } from 'discord.js';
+
+
+ ```ts title="src/app.ts"
+ import { Client } from 'discord.js';
-const client = new Client({
- intents: ['Guilds'],
-});
+ const client = new Client({
+ intents: ['Guilds'],
+ });
-client.token = '...'; // Optional: Manually set a bot token
+ client.token = '...'; // Optional: Manually set a bot token
-export default client;
-```
+ export default client;
+ ```
+
+
+
+ ```js title="src/app.js"
+ import { Client } from 'discord.js';
+
+ const client = new Client({
+ intents: ['Guilds'],
+ });
+
+ client.token = '...'; // Optional: Manually set a bot token
+
+ export default client;
+ ```
+
+
+
With the current entrypoint file created, it's important to understand
that:
@@ -71,26 +103,57 @@ that:
## Adding commands
To add a command, create a folder inside the `src/app` directory
-called `commands` and create your command file (e.g. `ping.ts`). This
-example will use a simple ping/pong command which will register as a
-chat input (slash) and message command.
-
-```ts title="src/app/commands/ping.ts"
-import type { ChatInputCommand, CommandData, MessageCommand } from 'commandkit';
-
-export const command: CommandData = {
- name: 'ping',
- description: 'Pong!',
-};
-
-export const chatInput: ChatInputCommand = async ({ interaction }) => {
- await interaction.reply('Pong!');
-};
-
-export const message: MessageCommand = async ({ message }) => {
- await message.reply('Pong!');
-};
-```
+called `commands` and create your command file. This example will use
+a simple ping/pong command which will register as a chat input (slash)
+and message command.
+
+
+
+ ```ts title="src/app/commands/ping.ts"
+ import type { ChatInputCommand, CommandData, MessageCommand } from 'commandkit';
+
+ export const command: CommandData = {
+ name: 'ping',
+ description: 'Pong!',
+ };
+
+ export const chatInput: ChatInputCommand = async ({ interaction }) => {
+ await interaction.reply('Pong!');
+ };
+
+ export const message: MessageCommand = async ({ message }) => {
+ await message.reply('Pong!');
+ };
+ ```
+
+
+
+ ```js title="src/app/commands/ping.js"
+ /**
+ * @typedef {import('commandkit').ChatInputCommand} ChatInputCommand
+ * @typedef {import('commandkit').CommandData} CommandData
+ * @typedef {import('commandkit').MessageCommand} MessageCommand
+ */
+
+ /** @type {CommandData} */
+ export const command = {
+ name: 'ping',
+ description: 'Pong!',
+ };
+
+ /** @type {ChatInputCommand} */
+ export const chatInput = async ({ interaction }) => {
+ await interaction.reply('Pong!');
+ };
+
+ /** @type {MessageCommand} */
+ export const message = async ({ message }) => {
+ await message.reply('Pong!');
+ };
+ ```
+
+
+
This command will reply with "Pong!" when the user runs the `/ping`
slash command, or sends `!ping` in the chat.
@@ -117,13 +180,29 @@ respective event is emitted by discord.js. Following the `clientReady`
event example mentioned above, you may want to log when your bot comes
online. The function for that will look like so:
-```ts title="src/app/events/clientReady/log.ts"
-import type { Client } from 'discord.js';
-
-export default function (client: Client) {
- console.log(`Logged in as ${client.user.username}!`);
-}
-```
+
+
+ ```ts title="src/app/events/clientReady/log.ts"
+ import type { Client } from 'discord.js';
+
+ export default function (client: Client) {
+ console.log(`Logged in as ${client.user.username}!`);
+ }
+ ```
+
+
+
+ ```js title="src/app/events/clientReady/log.js"
+ /**
+ * Event handler for when the bot is ready
+ * @param {import('discord.js').Client} client - The Discord client instance
+ */
+ export default function (client) {
+ console.log(`Logged in as ${client.user.username}!`);
+ }
+ ```
+
+
:::tip