Embeds V2
Overview
glyria.js ships with a first-class builder for Discord's Components V2 — the new message system that replaces classic embeds with a fully composable layout.
const embed = new EmbedV2Builder()
.container({ accentColor: 0x5865F2 })
.textDisplay("# Hello!")
.textDisplay("Welcome to the server.")
.end()
.build()
await ctx.reply({ ...embed })
.build() directly into your reply — not inside embeds: [].// ✅ correct
await ctx.reply({ ...embed })
// ❌ incorrect
await ctx.reply({ embeds: [embed] })
EmbedV2Builder is available globally — no import needed.Container
The container is the main building block. It wraps your content and supports an optional accent color:
new EmbedV2Builder()
.container({ accentColor: 0x5865F2 })
.textDisplay("Content here")
.end()
.build()
| Option | Type | Description |
|---|---|---|
accentColor | number | Left border color (hex as number) |
spoiler | boolean | Blur content until clicked |
Text display
Add markdown text anywhere inside a container:
.container()
.textDisplay("# Title")
.textDisplay("Some **bold** and *italic* text.")
.end()
Separator
Add visual spacing between sections:
.container()
.textDisplay("Section one")
.separator({ spacing: "large" })
.textDisplay("Section two")
.end()
| Option | Values | Description |
|---|---|---|
spacing | "small" | "large" | Spacing size |
divider | boolean | Show a divider line |
Section
A section pairs text with an accessory (button or thumbnail) on the right side:
.container()
.section()
.textDisplay("Choose your role")
.buttonAccessory({ label: "Pick", customId: "role_picker", style: "primary" })
.end()
.end()
With a thumbnail:
.section()
.textDisplay("Server info")
.thumbnailAccessory("https://example.com/icon.png", "Server icon")
.end()
textDisplay and exactly one accessory (buttonAccessory or thumbnailAccessory). Missing either will throw an error.Action row
Add clickable buttons below your content:
.container()
.textDisplay("Are you sure?")
.actionRow()
.button({ label: "Confirm", customId: "confirm", style: "success" })
.button({ label: "Cancel", customId: "cancel", style: "danger" })
.end()
.end()
Button styles
| Style | Use case |
|---|---|
primary | Main action — requires customId |
secondary | Secondary action — requires customId |
success | Positive action — requires customId |
danger | Destructive action — requires customId |
link | External URL — requires url |
Button options
| Option | Type | Description |
|---|---|---|
label | string | Button text |
customId | string | Identifier for interaction handling |
style | string | Button style |
url | string | URL for link buttons |
emoji | object | Button emoji |
disabled | boolean | Disable the button |
Media gallery
Display up to 10 images in a grid:
.container()
.textDisplay("Gallery")
.mediaGallery([
{ url: "https://example.com/image1.png" },
{ url: "https://example.com/image2.png", description: "A caption" },
])
.end()
File
Attach a file to the message:
.container()
.file("attachment://report.pdf")
.end()
Multiple containers
Chain multiple containers in a single message:
new EmbedV2Builder()
.container({ accentColor: 0x57F287 })
.textDisplay("✅ Action completed")
.end()
.separator()
.container()
.textDisplay("Here are the details...")
.actionRow()
.button({ label: "View", customId: "view_details", style: "secondary" })
.end()
.end()
.build()
Global footer
If configured in glyria.config.ts, a footer is automatically appended to every container:
// glyria.config.ts
export default defineConfig({
theme: {
embedV2: {
footer: { text: "My Bot • v1.0" }
}
}
})
No extra code needed in your commands — glyria.js handles it automatically.
Full example
export default new GlyriaCommand()
.setName("config")
.setDescription("Bot configuration")
.addSubCommandGroup((group) =>
group
.setName("logs")
.setDescription("Logs configuration")
.addSubCommand((cmd) =>
cmd
.setName("update")
.setDescription("Update logs settings")
.addBooleanOption((option) =>
option
.setName("enabled")
.setDescription("Enable logs")
.setRequired(true)
)
.execute(async (ctx) => {
const embed = new EmbedV2Builder()
.container({ accentColor: 0x5865F2 })
.textDisplay("Logs configuration updated!")
.separator({ spacing: "large" })
.section()
.textDisplay("Disable logs")
.buttonAccessory({ label: "Disable", style: "link", url: "https://discord.com" })
.end()
.actionRow()
.button({ label: "Enable", style: "link", url: "https://discord.com" })
.end()
.end()
.build()
await ctx.reply({ ...embed })
})
)
)

