Hello fellow Discord users!
If you've been hanging out in the Discord community, you've likely heard whispers about the next big thing: Components V2. Yes, it's finally arrived, and it's going to change the way we interact on this platform for the better. So sit back, pull up your drink of choice, and let's get down to business discussing what Components V2 is and how you can start using it!
Alright, let's dissect. V2 Components brings a new means for developers to add more power to their servers and make the experience better for users. It's like an update to your current toolkit that enables you to have richer interactions directly within your Discord server. From the buttons you can click on to dropdown menus and beyond, these components enable a more convenient way to interact without ever leaving the conversation.
Imagine being able to insert a new design into your bot commands output or enhance interactive menus cleaner and more interesting. Doesn't sound so bad, huh? This new set of components is all about refining your Discord experience cleaner, faster, and a whole lot more interactive!
If you're a developer or a server admin, the initial step is to ensure you update your Discord bot with the latest API changes. Ensure you check out the Discord Developer Portal for all the resources and latest news you'll need.
Once you're ready, you can start creating your components. Below are some of the essentials you can create:
Buttons: Simply interactive elements that people can click to do something—like create a ticket or participate in a giveaway.
Select Menus: Ideal to offer people options! You can add dropdown menus so people can choose from selections (like choosing a role or selecting a channel).
Containers: This is perhaps the most fascinating feature. Containers allow you to give a new face to the menu that you are building and a new way of making your community curious. Now, you can use "separators" inside these containers to separate text, buttons, etc.
Here we have a simple slash command that sends a button with the label set "Ping!", after the button is pressed the bot replies with "Pong!" and the latency of the bot. Then the button get's disabled.
// Calling our requierments
const { Client, GatewayIntentBits, REST, Routes, SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
// Setting our variables
const TOKEN = 'YOUR_BOT_TOKEN';
const CLIENT_ID = 'YOUR_CLIENT_ID';
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.once('ready', async () => {
console.log(`✅ Logged in as ${client.user.tag}`);
// Register the /ping command
const commands = [
new SlashCommandBuilder()
.setName('ping')
.setDescription('Sends a ping button')
.toJSON()
];
const rest = new REST({ version: '10' }).setToken(TOKEN);
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('✅ Slash command registered');
});
// When the command is used it sends the button
client.on('interactionCreate', async interaction => {
if (interaction.isChatInputCommand() && interaction.commandName === 'ping') {
const components = [
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setStyle(ButtonStyle.Secondary)
.setLabel("Ping!")
.setCustomId("ping_button"),
),
];
await interaction.reply({ components: components, flags: MessageFlags.IsComponentsV2 | MessageFlags.IsPersistent});
}
// Sends the response after the button was clicked
if (interaction.isButton() && interaction.customId === 'ping_button') {
const ping = client.ws.ping;
await interaction.reply({ content: `🏓 Pong! Latency is ${ping}ms`, ephemeral: true });
}
});
client.login(TOKEN);
**Now let's start our bot and see what happens.

**As we can see the command gets registered and can be used.

**After we use the command, we can see that the bot sends the button with a more modern look (round edges and a nice dark grey background)

**After we press the button, we can see that the bot replies to the message and sends the specific message that we set and sends the latency.
Here we have a simple command that sends dropdown menu that we can use to select different custom options.
// Calling our requierments
const { Client, GatewayIntentBits, REST, Routes, SlashCommandBuilder, ActionRowBuilder, MessageFlags, StringSelectMenuBuilder, StringSelectMenuOptionBuilder } = require('discord.js');
// Setting our variables
const TOKEN = 'YOUR_BOT_TOKEN';
const CLIENT_ID = 'YOUR_CLIENT_ID';
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.once('ready', async () => {
console.log(`✅ Logged in as ${client.user.tag}`);
// Register the /menu command
const commands = [
new SlashCommandBuilder()
.setName('menu')
.setDescription('Sends a dropdown menu!')
.toJSON()
];
const rest = new REST({ version: '10' }).setToken(TOKEN);
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('✅ Slash command registered');
});
// The bot sends dropdown menu after the command was used
client.on('interactionCreate', async interaction => {
if (interaction.isChatInputCommand() && interaction.commandName === 'menu') {
const components = [
new ActionRowBuilder()
.addComponents(
new StringSelectMenuBuilder()
.setCustomId("dropdown_menu")
.setPlaceholder("Plan selector")
.addOptions(
new StringSelectMenuOptionBuilder()
.setLabel("Discord Bot hosting")
.setDescription("(cheapest option)")
.setValue("discord_hosting")
.setEmoji({
name: "🤖",
}),
new StringSelectMenuOptionBuilder()
.setLabel("Game Hosting")
.setValue("game_hosting")
.setDescription("(best resources)")
.setEmoji({
name: "🎮",
}),
new StringSelectMenuOptionBuilder()
.setLabel("Web hosting")
.setValue("web_hosting")
.setEmoji({
name: "🌐",
}),
),
),
];
await interaction.reply({ components: components, flags: MessageFlags.IsComponentsV2 | MessageFlags.IsPersistent});
}
if (interaction.isStringSelectMenu() && interaction.customId === 'dropdown_menu') {
const selection = interaction.values[0];
let response;
if (selection === 'discord_hosting') {
response = '🤖 You selected **Discord Bot Hosting**.';
} else if (selection === 'game_hosting') {
response = '🎮 You selected **Game Hosting**.';
} else if (selection === 'web_hosting') {
response = '🌐 You selected **Web Hosting**.';
}
await interaction.reply({ content: response, ephemeral: true });
}
});
client.login(TOKEN);
**Now let's start the bot and see what happens.

**As we can see the command gets registered and can be used.

**After we use the command the dropdown menu gets sent and now we can use it like a normal one but now the options can have a little description and they also have a new modern look



**If we select any option, we can see that the bot sends a confirmation message of the option that we've selected. Now of course this doesn't do much, just telling us what we've selected but you develop a more advanced command that maybe gives a role to the user or creates a voice channel that they only have access to it. Your imagination is your limit, you can do a lot of things with these dropdown menus!
**Here I am going to show an example of a command that sends a container with some text and buttons that you can interact with.
// Calling our requierments
const { Client, GatewayIntentBits, REST, Routes, SlashCommandBuilder, ActionRowBuilder, MessageFlags, TextDisplayBuilder, SeparatorBuilder, SeparatorSpacingSize, ButtonBuilder, ButtonStyle, ContainerBuilder } = require('discord.js');
// Setting our variables
const TOKEN = 'YOUR_BOT_TOKEN';
const CLIENT_ID = 'YOUR_CLIENT_ID';
// Register the /plan command
const commands = [
new SlashCommandBuilder()
.setName('plan')
.setDescription('Sends a container plan!')
.toJSON()
];
const rest = new REST({ version: '10' }).setToken(TOKEN);
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('✅ Slash command registered');
});
// The bot sends the container after the command was used
client.on('interactionCreate', async interaction => {
if (interaction.isChatInputCommand() && interaction.commandName === 'plan') {
const components = [
new ContainerBuilder()
.addTextDisplayComponents(
new TextDisplayBuilder().setContent("## Welcome to Cybrancee!"),
)
.addTextDisplayComponents(
new TextDisplayBuilder().setContent("Please select the plan you want to join!"),
)
.addSeparatorComponents(
new SeparatorBuilder().setSpacing(SeparatorSpacingSize.Small).setDivider(true),
)
.addActionRowComponents(
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setStyle(ButtonStyle.Primary)
.setLabel("Discord Bot Hosting")
.setCustomId("plan_bot"),
new ButtonBuilder()
.setStyle(ButtonStyle.Success)
.setLabel("Game Hosting")
.setCustomId("plan_game"),
new ButtonBuilder()
.setStyle(ButtonStyle.Danger)
.setLabel("Web Hosting")
.setCustomId("plan_web"),
),
)
.addSeparatorComponents(
new SeparatorBuilder().setSpacing(SeparatorSpacingSize.Small).setDivider(true),
)
.addActionRowComponents(
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setStyle(ButtonStyle.Link)
.setLabel("Visit our website!")
.setEmoji({
name: "🌐",
})
.setURL("https://cybrancee.com/"),
),
),
];
await interaction.reply({ components: components, flags: MessageFlags.IsComponentsV2 | MessageFlags.IsPersistent});
}});
client.on('interactionCreate', async interaction => {
if (!interaction.isButton()) return;
switch (interaction.customId) {
case 'plan_bot':
await interaction.reply({ content: '🤖 You selected **Discord Bot Hosting**.', ephemeral: true });
break;
case 'plan_game':
await interaction.reply({ content: '🎮 You selected **Game Hosting**.', ephemeral: true });
break;
case 'plan_web':
await interaction.reply({ content: '🌐 You selected **Web Hosting**.', ephemeral: true });
break;
}
});
client.login(TOKEN);
**Now let's start the bot and see what happens.

**The bot as always registers the command and then we can use it in any channel.

**After we use the command we can see that the bot sends the container that has a new look, plus it has the buttons placed inside of it and I don't know if you saw it already but we now can have "separators" that separate buttons, text, etc...
**We can see that the buttons can have different colors and can be place 5 per row.
We can also have link buttons that send us to a specific website that we've set.




**As always if we press any of the buttons, it sends us a confirmation and the link buttons sends us to the website.
But this is not all of it, just by adding this line of code when creating the container, you can mark it as spoiler.
.setSpoiler(true)

Now that you've built your components, it's time to place them in your server! You can make commands that correspond to each of your components (as we saw at the previous section), so when users press a button or select an option, your bot responds accordingly. This is how you get infinite possibilities—hosting polls, organizing events, and so much more!
Prior to rolling out these new features to your whole community, test them first. Get a few users to give you feedback. This will allow you to sort out anything that won't work exactly right and to make changes based on real user experience.
You might be wondering, "Do I need this?" If you want to increase your community involvement and enrich your server with more dynamism, then yes! Components V2 streamlines communication and enables players to enjoy themselves while participating in activities. It's all about creating an energetic, interactive atmosphere where everyone can interact with each other.
Components V2 is released, and it's a “game-changer” for users and server admins alike. By embracing these new features, you can alter how users engage in your server, making every discord server slightly more interactive. Whether you're a professional developer or just starting out, there's something for everyone here that is worth trying.
So, what do you think? Are you up for trying out Components V2?
denis_xd_7