Skip to content

@lunibee/builders

The @lunibee/builders package helps you build Discord payloads without manually remembering every field and validation rule.

Terminal window
bun add @lunibee/builders
import { EmbedBuilder } from "@lunibee/builders";
const embed = new EmbedBuilder()
.setTitle("Server Moderation Log")
.setDescription("A member was banned from the server.")
.setColor(0xed4245)
.setTimestamp();
await channel.send({ embeds: [embed] });

You can add authors, footers, thumbnails, images, URLs, and fields as needed.

import { SlashCommandBuilder } from "@lunibee/builders";
const command = new SlashCommandBuilder()
.setName("ban")
.setDescription("Bans a member from the server")
.addUserOption(option =>
option
.setName("target")
.setDescription("The user to ban")
.setRequired(true)
);
const payload = command.toJSON();

toJSON() gives you the payload that can be sent through the command registration API.

import {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
} from "@lunibee/builders";
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("ticket_close")
.setLabel("Close ticket")
.setStyle(ButtonStyle.Danger),
);
await channel.send({
content: "Ticket controls",
components: [row],
});
import {
ActionRowBuilder,
StringSelectBuilder,
} from "@lunibee/builders";
const row = new ActionRowBuilder<StringSelectBuilder>().addComponents(
new StringSelectBuilder()
.setCustomId("select_roles")
.setPlaceholder("Choose a role")
.addOptions(
{ label: "Announcements", value: "announcements" },
{ label: "Updates", value: "updates" },
),
);
import {
ModalBuilder,
ActionRowBuilder,
TextInputBuilder,
TextInputStyle,
} from "@lunibee/builders";
const modal = new ModalBuilder()
.setCustomId("modal_ticket")
.setTitle("Create Support Ticket")
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setCustomId("ticket_subject")
.setLabel("Subject")
.setStyle(TextInputStyle.Short)
.setRequired(true),
),
);
import { AttachmentBuilder } from "@lunibee/builders";
const file = new AttachmentBuilder(imageBuffer, {
name: "welcome.png",
description: "Custom welcome banner",
});
await channel.send({ files: [file] });

The usual flow is:

Builder → toJSON() → Client/resource/REST → Discord

Builders create and validate payloads; they do not send requests themselves.