Build a Slackbot
Last updated Apr 8, 2026 In this tutorial, you will build a Slack ↗︎ bot using Cloudflare Workers. Your bot will make use of GitHub webhooks to send messages to a Slack channel when issues are updated or created, and allow users to write a command to look up GitHub issues from inside Slack.

This tutorial is recommended for people who are familiar with writing web applications. You will use TypeScript as the programming language and Hono ↗︎ as the web framework. If you have built an application with tools like Node ↗︎ and Express ↗︎, this project will feel very familiar to you. If you are new to writing web applications or have wanted to build something like a Slack bot in the past, but were intimidated by deployment or configuration, Workers will be a way for you to focus on writing code and shipping projects.
If you would like to review the code or how the bot works in an actual Slack channel before proceeding with this tutorial, you can access the final version of the codebase on GitHub ↗︎. From GitHub, you can add your own Slack API keys and deploy it to your own Slack channels for testing.
Before you start
All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3 ↗︎, and Wrangler.
Set up Slack
This tutorial assumes that you already have a Slack account, and the ability to create and manage Slack applications.
Configure a Slack application
To post messages from your Cloudflare Worker into a Slack channel, you will need to create an application in Slack’s UI. To do this, go to Slack’s API section, at api.slack.com/apps ↗︎, and select Create New App.

Slack applications have many features. You will make use of two of them, Incoming Webhooks and Slash Commands, to build your Worker-powered Slack bot.
Incoming Webhook
Incoming Webhooks are URLs that you can use to send messages to your Slack channels. Your incoming webhook will be paired with GitHub’s webhook support to send messages to a Slack channel whenever there are updates to issues in a given repository. You will see the code in more detail as you build your application. First, create a Slack webhook:
- On the sidebar of Slack's UI, select Incoming Webhooks.
- In Webhook URLs for your Workspace, select Add New Webhook to Workspace.
- On the following screen, select the channel that you want your webhook to send messages to (you can select a room, like #general or #code, or be messaged directly by your Slack bot when the webhook is called.)
- Authorize the new webhook URL.
After authorizing your webhook URL, you will be returned to the Incoming Webhooks page and can view your new webhook URL. You will add this into your Workers code later. Next, you will add the second component to your Slack bot: a Slash Command.

Slash Command
A Slash Command in Slack is a custom-configured command that can be attached to a URL request. For example, if you configured /weather <zip>, Slack would make an HTTP POST request to a configured URL, passing the text <zip> to get the weather for a specified zip code. In your application, you will use the /issue command to look up GitHub issues using the GitHub API ↗︎. Typing /issue cloudflare/wrangler#1 will send the text cloudflare/wrangler#1 in a HTTP POST request to your application, which the application will use to find the relevant GitHub issue ↗︎.
- On the Slack sidebar, select Slash Commands.
- Create your first slash command.
For this tutorial, you will use the command /issue. The request URL should be the /lookup path on your application URL: for example, if your application will be hosted at https://myworkerurl.com, the Request URL should be https://myworkerurl.com/lookup.

Configure your GitHub Webhooks
Your Cloudflare Workers application will be able to handle incoming requests from Slack. It should also be able to receive events directly from GitHub. If a GitHub issue is created or updated, you can make use of GitHub webhooks to send that event to your Workers application and post a corresponding message in Slack.
To configure a webhook:
- Go to your GitHub repository's Settings > Webhooks > Add webhook.
If you have a repository like https://github.com/user/repo, you can access the Webhooks page directly at https://github.com/user/repo/settings/hooks.
- Set the Payload URL to the
/webhookpath on your Worker URL.
For example, if your Worker will be hosted at https://myworkerurl.com, the Payload URL should be https://myworkerurl.com/webhook.
- In the Content type dropdown, select application/json.
The Content type for your payload can either be a URL-encoded payload (application/x-www-form-urlencoded) or JSON (application/json). For the purpose of this tutorial and to make parsing the payload sent to your application, select JSON.
- In Which events would you like to trigger this webhook?, select Let me select individual events.
GitHub webhooks allow you to specify which events you would like to have sent to your webhook. By default, the webhook will send push events from your repository. For the purpose of this tutorial, you will choose Let me select individual events.
- Select the Issues event type.
There are many different event types that can be enabled for your webhook. Selecting Issues will send every issue-related event to your webhook, including when issues are opened, edited, deleted, and more. If you would like to expand your Slack bot application in the future, you can select more of these events after the tutorial.
- Select Add webhook.

When your webhook is created, it will attempt to send a test payload to your application. Since your application is not actually deployed yet, leave the configuration as it is. You will later return to your repository to create, edit, and close some issues to ensure that the webhook is working once your application is deployed.
Init
To initiate the project, use the command line interface C3 (create-cloudflare-cli) ↗︎.
npmyarnpnpm
npm create cloudflare@latest -- slack-bot
yarn create cloudflare slack-bot
pnpm create cloudflare@latest slack-bot
Follow these steps to create a Hono project.
- For What would you like to start with?, select
Framework Starter. - For Which development framework do you want to use?, select
Hono. - For, Do you want to deploy your application?, select
No.
Go to the slack-bot directory:
cd slack-bot
Open src/index.ts in an editor to find the following code.
import { Hono } from "hono";
type Bindings = {
[key in keyof CloudflareBindings]: CloudflareBindings[key];
};
const app = new Hono<{ Bindings: Bindings }>();
app.get("/", (c) => {
return c.text("Hello Hono!");
});
export default app;
This is a minimal application using Hono. If a GET access comes in on the path /, it will return a response with the text Hello Hono!. It also returns a message 404 Not Found with status code 404 if any other path or method is accessed.
To run the application on your local machine, execute the following command.
npmyarnpnpmbun
npm i -- dev
yarn add dev
pnpm add dev
bun add dev
Access to http://localhost:8787 in your browser after the server has been started, and you can see the message.
Hono helps you to create your Workers application easily and quickly.
Build
Now, let's create a Slack bot on Cloudflare Workers.
Separating files
You can create your application in several files instead of writing all endpoints and functions in one file. With Hono, it is able to add routing of child applications to the parent application using the function app.route().
For example, imagine the following Web API application.
import { Hono } from "hono";
const app = new Hono();
app.get("/posts", (c) => c.text("Posts!"));
app.post("/posts", (c) => c.text("Created!", 201));
export default app;
You can add the routes under /api/v1.
import { Hono } from "hono";
import api from "./api";
const app = new Hono();
app.route("/api/v1", api);
export default app;
It will return Posts! when accessing GET /api/v1/posts.
The Slack bot will have two child applications called "route" each.
lookuproute will take requests from Slack (sent when a user uses the/issuecommand), and look up the corresponding issue using the GitHub API. This application will be added to/lookupin the main application.webhookroute will be called when an issue changes on GitHub, via a configured webhook. This application will be add to/webhookin the main application.
Create the route files in a directory named routes.
Create new folders and filessh
mkdir -p src/routes
touch src/routes/lookup.ts
touch src/routes/webhook.ts
Then update the main application.
import { Hono } from "hono";
import lookup from "./routes/lookup";
import webhook from "./routes/webhook";
const app = new Hono();
app.route("/lookup", lookup);
app.route("/webhook", webhook);
export default app;
Defining TypeScript types
Before implementing the actual functions, you need to define the TypeScript types you will use in this project. Create a new file in the application at src/types.ts and write the code. Bindings is a type that describes the Cloudflare Workers environment variables. Issue is a type for a GitHub issue and User is a type for a GitHub user. You will need these later.
export type Bindings = {
SLACK_WEBHOOK_URL: string;
};
export type Issue = {
html_url: string;
title: string;
body: string;
state: string;
created_at: string;
number: number;
user: User;
};
type User = {
html_url: string;
login: string;
avatar_url: string;
};
Creating the lookup route
Start creating the lookup route in src/routes/lookup.ts.
import { Hono } from "hono";
const app = new Hono();
export default app;
To understand how you should design this function, you need to understand how Slack slash commands send data to URLs.
According to the documentation for Slack slash commands ↗︎, Slack sends an HTTP POST request to your specified URL, with a application/x-www-form-urlencoded content type. For example, if someone were to type /issue cloudflare/wrangler#1, you could expect a data payload in the format:
