A framework for building Slack apps, fast.
—
The App class is the central component of Slack Bolt, providing event-driven architecture for building Slack applications with comprehensive listener registration, middleware support, and lifecycle management.
Creates a new Slack Bolt application instance with configuration options.
/**
* Creates a new Slack Bolt application instance
* @param options - Configuration options for the app
*/
constructor(options?: AppOptions);
interface AppOptions {
/** Bot token starting with xoxb- */
token?: string;
/** App-level token starting with xapp- (required for Socket Mode) */
appToken?: string;
/** Signing secret for request verification */
signingSecret?: string;
/** Custom receiver for handling HTTP requests */
receiver?: Receiver;
/** Custom authorization function */
authorize?: Authorize;
/** Custom logger instance */
logger?: Logger;
/** Log level for built-in logger */
logLevel?: LogLevel;
/** Ignore events from the bot itself */
ignoreSelf?: boolean;
/** Web API client options */
clientOptions?: WebClientOptions;
/** Conversation state store */
convoStore?: ConversationStore;
/** Enable Socket Mode connection */
socketMode?: boolean;
}Usage Example:
import { App } from "@slack/bolt";
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
socketMode: false, // Set to true for Socket Mode
logLevel: "INFO"
});Register listeners for Slack events with optional event type filtering.
/**
* Register listeners for Slack events
* @param eventType - Event type pattern to match
* @param listeners - Middleware functions to handle the event
*/
event<EventType extends string>(
eventType: EventType,
...listeners: Middleware<SlackEventMiddlewareArgs<EventType>>[]
): void;Usage Examples:
// Listen for app mentions
app.event("app_mention", async ({ event, say }) => {
await say(`Hello <@${event.user}>!`);
});
// Listen for when users join channels
app.event("member_joined_channel", async ({ event, client, logger }) => {
logger.info(`User ${event.user} joined channel ${event.channel}`);
});
// Listen for file shared events
app.event("file_shared", async ({ event, client }) => {
// Handle file shared event
});Register listeners for message events with optional pattern matching.
/**
* Register listeners for message events with optional pattern matching
* @param pattern - Text pattern to match (string or RegExp), optional
* @param listeners - Middleware functions to handle the message
*/
message(
pattern?: string | RegExp,
...listeners: Middleware<SlackEventMiddlewareArgs<'message'>>[]
): void;Usage Examples:
// Listen for all messages
app.message(async ({ message, say }) => {
if (message.subtype === undefined) {
await say("I heard you!");
}
});
// Listen for messages containing "hello"
app.message("hello", async ({ message, say }) => {
await say(`Hey there <@${message.user}>!`);
});
// Listen for messages matching a pattern
app.message(/^ticket-(\d+)/, async ({ message, say, context }) => {
const ticketId = context.matches[1];
await say(`Looking up ticket ${ticketId}...`);
});Register listeners for interactive component actions (buttons, select menus, etc.).
/**
* Register listeners for interactive component actions
* @param actionId - Action ID or constraint object to match
* @param listeners - Middleware functions to handle the action
*/
action<ActionId extends string>(
actionId: ActionId | ActionConstraints,
...listeners: Middleware<SlackActionMiddlewareArgs>[]
): void;Usage Examples:
// Listen for button clicks
app.action("button_click", async ({ body, ack, say }) => {
await ack();
await say(`<@${body.user.id}> clicked the button`);
});
// Listen for select menu selections
app.action("static_select-action", async ({ body, ack, client }) => {
await ack();
// Handle select menu selection
});
// Listen for overflow menu actions
app.action("overflow_menu_action", async ({ action, ack, respond }) => {
await ack();
await respond(`You selected: ${action.selected_option.value}`);
});Register listeners for slash commands.
/**
* Register listeners for slash commands
* @param commandName - Slash command name (e.g., "/hello")
* @param listeners - Middleware functions to handle the command
*/
command(
commandName: string,
...listeners: Middleware<SlackCommandMiddlewareArgs>[]
): void;Usage Examples:
// Handle /hello command
app.command("/hello", async ({ command, ack, respond }) => {
await ack();
await respond(`Hey there <@${command.user_id}>!`);
});
// Handle /ticket command with parameters
app.command("/ticket", async ({ command, ack, client, respond }) => {
await ack();
const args = command.text.split(" ");
const action = args[0];
if (action === "create") {
await respond("Creating a new ticket...");
} else if (action === "list") {
await respond("Listing your tickets...");
} else {
await respond("Usage: /ticket create|list");
}
});Register listeners for shortcuts (global and message shortcuts).
/**
* Register listeners for shortcuts
* @param callbackId - Shortcut callback ID to match
* @param listeners - Middleware functions to handle the shortcut
*/
shortcut<CallbackId extends string>(
callbackId: CallbackId | ShortcutConstraints,
...listeners: Middleware<SlackShortcutMiddlewareArgs>[]
): void;Usage Examples:
// Handle global shortcut
app.shortcut("open_modal", async ({ shortcut, ack, client, body }) => {
await ack();
await client.views.open({
trigger_id: body.trigger_id,
view: {
type: "modal",
callback_id: "my_modal",
title: { type: "plain_text", text: "My App" },
close: { type: "plain_text", text: "Cancel" },
blocks: [
// Modal blocks here
]
}
});
});
// Handle message shortcut
app.shortcut("share_message", async ({ shortcut, ack, client }) => {
await ack();
// Handle sharing the message
});Register listeners for modal view submissions and closures.
/**
* Register listeners for view submissions and closures
* @param callbackId - View callback ID to match
* @param listeners - Middleware functions to handle the view action
*/
view<CallbackId extends string>(
callbackId: CallbackId | ViewConstraints,
...listeners: Middleware<SlackViewMiddlewareArgs>[]
): void;Usage Examples:
// Handle modal submission
app.view("modal_callback", async ({ ack, body, view, client }) => {
await ack();
const values = view.state.values;
const user = body.user.id;
// Process form data
});
// Handle modal closure
app.view({ callback_id: "modal_callback", type: "view_closed" },
async ({ ack, body, view }) => {
await ack();
// Handle modal being closed
}
);Add middleware that runs for all incoming requests.
/**
* Add global middleware that runs for all requests
* @param middlewares - Middleware functions to add
*/
use(...middlewares: Middleware<AnyMiddlewareArgs>[]): void;Usage Examples:
// Add custom logging middleware
app.use(async ({ logger, body, next }) => {
logger.info("Incoming request", body);
await next();
});
// Add authorization middleware
app.use(async ({ context, client, next }) => {
// Add custom context properties
context.customData = await loadUserData(context.userId);
await next();
});
// Add built-in middleware
import { ignoreSelf } from "@slack/bolt";
app.use(ignoreSelf);Register global error handler for unhandled errors.
/**
* Register global error handler
* @param errorHandler - Function to handle errors
*/
error(errorHandler: (error: CodedError) => Promise<void>): void;Usage Example:
app.error(async (error) => {
console.error("An error occurred:", error);
// Send error to monitoring service
if (error.code === "slack_bolt_authorization_error") {
// Handle authorization errors
}
});Start and stop the Slack application.
/**
* Start the Slack application
* @param port - Port number for HTTP server (optional)
* @returns Promise that resolves when the app starts
*/
start(port?: number): Promise<unknown>;
/**
* Stop the Slack application
* @returns Promise that resolves when the app stops
*/
stop(): Promise<unknown>;Usage Examples:
// Start the app
(async () => {
await app.start(3000);
console.log("⚡️ Bolt app is running on port 3000!");
})();
// Graceful shutdown
process.on("SIGINT", async () => {
await app.stop();
process.exit(0);
});Register listeners for select menu options and custom functions.
/**
* Register listeners for external select menu options
* @param actionId - Action ID or constraints to match
* @param listeners - Middleware functions to handle options request
*/
options<ActionId extends string>(
actionId: ActionId | OptionsConstraints,
...listeners: Middleware<SlackOptionsMiddlewareArgs>[]
): void;
/**
* Register listeners for custom functions
* @param callbackId - Function callback ID to match
* @param listeners - Middleware functions to handle function execution
*/
function<CallbackId extends string>(
callbackId: CallbackId,
...listeners: Middleware<SlackCustomFunctionMiddlewareArgs>[]
): void;Usage Examples:
// Handle external select menu options
app.options("external_select", async ({ options, ack }) => {
await ack({
options: [
{ text: { type: "plain_text", text: "Option 1" }, value: "opt1" },
{ text: { type: "plain_text", text: "Option 2" }, value: "opt2" }
]
});
});
// Handle custom function execution
app.function("my_function", async ({ inputs, complete, fail }) => {
try {
const result = await processInputs(inputs);
await complete({ outputs: result });
} catch (error) {
await fail({ error: "Processing failed" });
}
});type Authorize = (
source: AuthorizeSourceData
) => Promise<AuthorizeResult>;
interface AuthorizeSourceData {
teamId: string;
enterpriseId?: string;
userId?: string;
conversationId?: string;
isEnterpriseInstall?: boolean;
}
interface AuthorizeResult {
botToken?: string;
userToken?: string;
botId?: string;
botUserId?: string;
userId?: string;
teamId?: string;
enterpriseId?: string;
}Install with Tessl CLI
npx tessl i tessl/npm-slack--bolt