Flexible Components replace traditional embeds with LEGO-like blocks – text, images, buttons and menus – giving you richer layouts and eliminating many Discord API errors such as "Invalid Form Body (type must be 1)".
• Node.js 16.9.0 or higher • discord.js 14.19.3 or higher • Always send the MessageFlags.IsComponentsV2 flag when replying or editing a reply
import { MessageFlags } from "discord.js";
await interaction.reply({
components: [/* your ContainerBuilder instance */],
flags: MessageFlags.IsComponentsV2
});
• 'ContainerBuilder' – //root component that holds everything else
• 'TextDisplayBuilder' – //Markdown-capable text block
• 'SectionBuilder' – //text plus ONE accessory (thumbnail or button) on the right
• 'ThumbnailBuilder' – //thumbnail image accessory
• 'MediaGalleryBuilder' – //grid / gallery of images
• 'MediaGalleryItemBuilder' – //a single image inside the gallery
• 'ActionRowBuilder' – //horizontal row for buttons or select menus
• 'ButtonBuilder' – //creates a button
• 'StringSelectMenuBuilder' – //creates a dropdown menu
• 'SeparatorBuilder' – //simple horizontal divider
const container = new ContainerBuilder();
interaction.reply({ components: [container], flags: MessageFlags.IsComponentsV2 });
interaction.deferReply({ flags: MessageFlags.IsComponentsV2 | MessageFlags.Ephemeral });
// heavy work here …
interaction.editReply({ components: [container], flags: MessageFlags.IsComponentsV2 });
const header = new SectionBuilder()
.addTextDisplayComponents(new TextDisplayBuilder().setContent("### Character Sheet"))
.setThumbnailAccessory(new ThumbnailBuilder().setURL("IMAGE_URL"));
container.addSectionComponents(header);
const gallery = new MediaGalleryBuilder().addItems(
new MediaGalleryItemBuilder().setURL("IMAGE_URL").setDescription("Awesome picture")
);
container.addMediaGalleryComponents(gallery);
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder().setCustomId("ok").setLabel("OK").setStyle(ButtonStyle.Primary),
new ButtonBuilder().setCustomId("cancel").setLabel("Cancel").setStyle(ButtonStyle.Danger)
);
container.addActionRowComponents(buttons);