Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/betterdiscord/betterdiscord/llms.txt

Use this file to discover all available pages before exploring further.

BdApi is the global API provided by BetterDiscord for plugin developers. It offers utilities for patching, data storage, UI creation, and accessing Discord’s internals.

Accessing BdApi

BdApi is available globally:
BdApi.UI.showToast("Hello World!");

Plugin-specific API instance

Create a bound instance for automatic plugin name tracking:
const api = new BdApi("MyPlugin");

// All calls are automatically associated with your plugin
api.Logger.info("Starting up");
api.Data.save("config", {enabled: true});

Core namespaces

Patcher

Modify existing functions to change Discord’s behavior.

before()

Run code before the original function:
BdApi.Patcher.before("MyPlugin", someModule, "functionName", (thisObject, args) => {
    // Modify arguments
    args[0] = "modified value";
});

after()

Run code after the original function and modify the return value:
BdApi.Patcher.after("MyPlugin", someModule, "functionName", (thisObject, args, returnValue) => {
    // Modify return value
    if (returnValue) {
        returnValue.modified = true;
    }
    return returnValue;
});

instead()

Replace the original function entirely:
BdApi.Patcher.instead("MyPlugin", someModule, "functionName", (thisObject, args, originalFunction) => {
    // Optionally call original
    const result = originalFunction.call(thisObject, ...args);
    
    // Return custom value
    return "custom return value";
});

unpatchAll()

Remove all patches created by your plugin:
BdApi.Patcher.unpatchAll("MyPlugin");
Always call unpatchAll() in your plugin’s stop() method to prevent conflicts.

Data

Persist plugin data to disk.

save()

Save data with a key:
BdApi.Data.save("MyPlugin", "settings", {
    enabled: true,
    theme: "dark"
});
With bound API:
const api = new BdApi("MyPlugin");
api.Data.save("settings", {enabled: true});

load()

Load previously saved data:
const settings = BdApi.Data.load("MyPlugin", "settings");

if (!settings) {
    // Use defaults
    settings = {enabled: true, theme: "dark"};
}

delete()

Delete stored data:
BdApi.Data.delete("MyPlugin", "settings");

Webpack

Find and access Discord’s internal modules.

getModule()

Find a single module:
const MessageActions = BdApi.Webpack.getModule(
    BdApi.Webpack.Filters.byKeys("sendMessage")
);
With options:
const module = BdApi.Webpack.getModule(
    BdApi.Webpack.Filters.byKeys("someFunction"),
    {searchExports: true, defaultExport: false}
);

getModules()

Find multiple matching modules:
const allModules = BdApi.Webpack.getModules(
    BdApi.Webpack.Filters.byKeys("render")
);

Filters

Built-in filters for finding modules:
// Find by property names
const filter = BdApi.Webpack.Filters.byKeys("sendMessage", "editMessage");

Stores

Access Discord’s Flux stores directly:
const {UserStore, ChannelStore, GuildStore} = BdApi.Webpack.Stores;

const currentUser = UserStore.getCurrentUser();
const channel = ChannelStore.getChannel("123456789");

UI

Create user interface elements.

showToast()

Display a toast notification:
BdApi.UI.showToast("Operation successful!", {
    type: "success",
    icon: true,
    timeout: 3000
});
type
string
Toast type: "info", "success", "warning", "error" (default: "info")
icon
boolean
Whether to show an icon (default: true)
timeout
number
Duration in milliseconds (default: 3000)

showNotice()

Display a notice banner:
const close = BdApi.UI.showNotice("Update available!", {
    type: "info",
    buttons: [{
        label: "Update",
        onClick: () => {
            // Handle update
        }
    }],
    timeout: 10000
});

// Close manually
close();

alert()

Show an alert modal:
BdApi.UI.alert("Warning", "This action cannot be undone.");

showConfirmationModal()

Show a confirmation dialog:
BdApi.UI.showConfirmationModal(
    "Delete Item",
    "Are you sure you want to delete this item?",
    {
        confirmText: "Delete",
        cancelText: "Cancel",
        danger: true,
        onConfirm: () => {
            // Delete the item
        },
        onCancel: () => {
            // Cancelled
        }
    }
);

buildSettingsPanel()

Create a settings panel (see Settings for details):
BdApi.UI.buildSettingsPanel({
    settings: [
        {
            type: "switch",
            id: "enabled",
            name: "Enable Feature",
            value: true,
            onChange: (value) => console.log(value)
        }
    ]
});

Logger

Log messages with proper formatting.
const api = new BdApi("MyPlugin");

api.Logger.log("General message");
api.Logger.info("Informational message");
api.Logger.warn("Warning message");
api.Logger.error("Error message");
api.Logger.debug("Debug message");
Output includes your plugin name:
[MyPlugin] Informational message

DOM

Manipulate the DOM safely.

addStyle()

Add CSS to the page:
BdApi.DOM.addStyle("MyPlugin", `
    .my-custom-class {
        color: red;
        font-weight: bold;
    }
`);

removeStyle()

Remove injected CSS:
BdApi.DOM.removeStyle("MyPlugin");

React and ReactDOM

Access Discord’s React instance:
const {React, ReactDOM} = BdApi;

const MyComponent = () => {
    const [count, setCount] = React.useState(0);
    
    return React.createElement("button", {
        onClick: () => setCount(count + 1)
    }, `Clicked ${count} times`);
};

Utils

Utility functions.

getNestedProp()

Safely access nested properties:
const value = BdApi.Utils.getNestedProp(obj, "deeply.nested.property");

className()

Generate className strings:
const className = BdApi.Utils.className(
    "base-class",
    condition && "conditional-class",
    {"active": isActive}
);

Plugins

Manage other plugins.
// Get plugin folder path
const folder = BdApi.Plugins.folder;

// Check if a plugin is enabled
const isEnabled = BdApi.Plugins.isEnabled("OtherPlugin");

// Enable/disable plugins
BdApi.Plugins.enable("OtherPlugin");
BdApi.Plugins.disable("OtherPlugin");
BdApi.Plugins.toggle("OtherPlugin");

// Reload a plugin
BdApi.Plugins.reload("OtherPlugin");

// Get plugin instance
const plugin = BdApi.Plugins.get("OtherPlugin");

// Get all plugins
const allPlugins = BdApi.Plugins.getAll();
Managing other plugins should be done carefully. Only enable/disable plugins with explicit user consent.

ContextMenu

Add items to context menus.
BdApi.ContextMenu.patch("user-context", (returnValue, props) => {
    returnValue.props.children.push(
        BdApi.ContextMenu.buildItem({
            type: "text",
            label: "My Custom Option",
            action: () => {
                console.log("Clicked!", props);
            }
        })
    );
});

Commands

Register slash commands.
const api = new BdApi("MyPlugin");

api.Commands.register({
    command: "hello",
    description: "Say hello",
    options: [
        {
            name: "name",
            description: "Name to greet",
            type: "STRING",
            required: false
        }
    ],
    execute: (args) => {
        const name = args.name || "World";
        return {content: `Hello, ${name}!`};
    }
});
Unregister in stop():
api.Commands.unregister("hello");

Components

Access to BetterDiscord React components. See Settings for component documentation.
const {Components} = BdApi;

// Available components
Components.SettingItem
Components.SwitchInput
Components.SliderInput
Components.TextInput
Components.DropdownInput
Components.NumberInput
Components.RadioInput
Components.KeybindInput
Components.ColorInput
Components.SearchInput
Components.SettingGroup
Components.ErrorBoundary
Components.Text
Components.Flex
Components.Button
Components.Spinner
Components.Tooltip

Version info

Get BetterDiscord version:
console.log(BdApi.version); // e.g., "1.9.0"