Making An Interactive Slack App - Part 1
How to create a fully interactive NodeJS Slack app with a slash command, buttons and more

If you want to create a Slack bot that only posts simple text content, you can easily find tutorials online. But when what you want is a bot that interacts with user through select menus or buttons, it then becomes harder to find content and to actually understand why a Slack bot user is not going to work.
Let me start with a key piece of information that took me many hours of research and trial & error to understand. Custom bot users are different than Slack apps. The former have more limited capabilities. They can listen to events, post messages, and read text responses. But they’re not able to use the cool buttons, select dropdowns, slash commands and more that Slack offers. A Slack app is a full capacity entity that can also contain a bot user. This article will explain how to create a full app that can ask multiple questions to users and react to their choices.
We will be using Node and Express. Our example app is going to be called Better Ally and will be an interactive tool for people who want to educate themselves on anti racism, anti sexism, LGBTQ+ issues, and autism (to keep it short, but there's much more we could add). It will ask a few questions to the user and according to their choices, provide a resource. This is only an example but there is a lot you can do with this model, and to give another example, I created an app that helps engineers assess the severity of an incident.
Table of contents
Getting Started
Before we get to the code, there are a few things we need to do in the Slack settings. Go to the Slack API app page and click Create New App
. Choose an app name and a workspace to tie it to. Next we need to add some permissions. Click the OAuth and permissions
tab and under Bot Token Scopes
add these scopes: app_mentions:read
, chat:write
, chat:write.customize
, commands
and links:write
. Click the Install App
tab in the left menu and install the app to your workspace. Keep this tab open, we will need it again later.
Creating A Node App
We’re now ready to start coding! Install Node if you don’t have it. Now in a terminal we can create a folder for our project mkdir better_ally
and move into it cd better_ally
. Now we need to ignore some files that should stay private,touch .gitignore
and add this in:
Now we can initialize node by typing npm init
and following the instructions. This will generate a package.json
file. We will need a few dependencies: Express web server, and DotEnv to manage environment variables locally. In the terminal still, typenpm install express --save
and npm install dotenv --save
. Create a new repository on Github and follow the instructions to initialize git, make an initial commit and push.
To store our environment variables, we will create a .env
file by typing touch .env
. Copy this in your .env
:
Now you’ll need to replace the dummy values with the signing secret and verification token you see in your Slack settings in the Basic Information
tab in the left menu. The bot token is in the OAuth And Permissions
tab in the left menu. Finally the port I set here is 5000
but it can be whichever port you want to use.
Now let’s create an index.js
file to put our first code in: touch index.js
. Let’s create a server an listen, add this code to index.js
:
Listening For Slack Events
Now that we have a server, we’re ready to listen to events. Slack has a great module for Node, that will do a lot of boilerplate for us. Install it by typing npm install @slack/events-api --save
in your terminal. Create an events.js
file and add this code to it:
Now that we have this code, we can call it from index.js
by adding this just before app.listen
:
const events = require('./events')
events.listenForEvents(app)
With this, we are adding a /events
route to our app and logging the info we receive when an app_mention
event is fired. There are a lot of events you can listen to, here is a full list.
To make this work, Slack needs an endpoint it can send events to, so we’re going to use Ngrok to make a local tunnel. Install Ngrok, and then type ./ngrok http 5000
to start tunneling the port we need. To make events work locally, Slack requires us to run a verification endpoint before we can add our url to its settings. In a terminal, at the root of our app, type ./node_modules/.bin/slack-verify --port 5000 --secret <signing_secret>
, replacing <signing_secret>
with your own.
Copy the url Ngrok gives you in the terminal running it. Now in your browser head back to the Slack settings for your app and under the Event Subscriptions
tab, turn the toggle on and paste your ngrok url, adding /events
to the end of it. It should say Verified
, right under, in Subscribe to bot events
, add the app_mention
event. Don’t forget to click Save changes
at the bottom. You can stop the verifying endpoint now, you’re good.
Start the app in your terminal with node index.js
and we can finally head to Slack to test it! You can create a testing public channel and invite our bot by typing /invite @better_ally #channel_name
. Now post a message containing @better_ally
and in your terminal you should see the console.log
with the payload received!
Responding To Events
Our app is going to provide information on how to be a better ally. So on app mention, the first thing we want to do is ask the user which subject they want to learn about. For that we will use a select menu element that will display a dropdown select box with all the options. I had to find that out the hard way because it doesn’t seem to be documented anywhere, but the button element in Slack only allows 5 options. If you try to add an 6th option, it will just ignore it. The select menu, on the other hand, allows up to 100 options (and that limit is documented, unlike the other one).
To do that, we will use Slack’s Web API to post our fancy select menu back to the user who mentioned our app. Let’s install it by running npm install @slack/web-api --save
in our terminal. Next, we need to modify our events.js
, that will now look like this:
When our app is mentioned in Slack, it will now call our new respondToEvent
function. This function will use the web API to post a message to the same channel it was mentioned in. The select menu will be in the attachment
attribute. Select menus are only one of the multiple interactive elements you can use in Slack, checkout this full list to see them all. Create a new folder called elements
and inside it, create a file called subjects.json
. Add this content to it:
To try it on let’s restart our app with node index.js
and mention @better_ally
again. You should get our select menu!

Voilà! You’ve got a super cool app that can answer when you call its name and ask you a first super cool question. In the next part, we will learn how to respond to Slack interactions, ie any action a user takes on a fancy element like buttons, select menus, and more.