How to build a Slack app

The story of PleaseMeet, send opt-in intros from Slack


Opt-in intros (ie, asking permission first) is the right way to introduce people. PleaseMeet makes it easy to send opt-in intros from Slack (Update: The app is not longer maintained and redirects to my main project, Smooz).

This article is a step-by-step demo of building a Slack app and the code is released in open source here.

The inspiration

In this article I want to demo building a Slack app. For this mini-project I was inspired by this tweet from Jean de La Rochebrochard about email intro from command line, as well as this article describing how they do it at Kima Ventures.

It is sometimes embarrassing when I get introduced to people without checking my interest beforehand, and I (almost) always (try to) request permission before making an intro myself. So I think turning the internal Kima tool into a public app can be useful.

I’ll be releasing the Github code in parallel as well as hosting it so that people can use it.

Choosing the app type

There are basically three main types of Slack apps, which roughly fall into three buckets

  • Incoming webhooks are for notifications (outside -> inside),
  • commands are for simple actions (inside -> outside),
  • and bots for two-sided interactions and conversational interfaces.

Of course one could use bots for notifications, or as a “super-command”, but they thrive in complex situations where they can either extract better context or provide richer informations through conversations.

For this project, I will keep things simple with a command app. If there is sufficient interest level, I may turn it into a bot later, because conversational interfaces can expose much more options without adding much in UX complexity. The app name? First thing that came to my mind: Please Meet.

Format the command

The keyword will obviously be /intro. There will be 3 actions

/intro <person1 email> <person2 email> <reason>

This command will send an email to each person, asking if she’s ok to be introduced to the other, for the reason mentioned. The email will have two link “yes” or “no”. If both say “yes”, another email will be sent to put them in touch.

I initially wanted to allow Slack handles, to be able to intro using DM instead of emails, but in terms of access rights and actions it’ll be for when I turn PleaseMeet into a bot app. Later, perhaps.

/intro status or /intro list

Listing all intros made by the sender with their yes/no/pending status.

/intro help

Because that’s a standard practice and people expect it.

Starting to code

I’m usually more a Rails person but my first Slack app,, was coded in Node.js so I will reuse some of the code. Training in a new language FTW!

I start with a boilerpalte Express app, then initiate a git repo on GitHub and an app of Heroku. In terms of routes, I need the following:

app.get(‘/’, function(req, res) {‘/intro’, function(req, res) {
 app.get(‘/yes’, function(req, res) {
 app.get(‘/no’, function(req, res) {
 app.get(‘/new’, function(req, res) {

The root page, the command endpoint, the two endpoints for the replies, and the redirect link to give to Slack Oauth as callback.

In terms of models, I don’t need a lot of data. I need to register the Teams that add the BePolite app, and record the Intros being made with five elements: the sender’s ID, personA and personB email + reply, the Reason text, and the status. The status is “pending” by default, and can later move to “accepted” or “declined”.

The Slack app

Moving on to the next step. I create an app on Slack, and add a command named /intro, obviously. The important part is to point the Request URL to the‘/intro’) route defined above.

The Request URL points to my POST route “/intro”

I copy the ID and Secret to Heroku config vars, as well as the Command token that will prove that requests are indeed coming from Slack.

Actually, I also create at the same time a copy app for development. The ID, Secret and Command token go to a .env file (not indexed by git), and the Request URL points to a LocalTunnel URL linked to my localhost server. This way, I can debug everything from my local computer without interfering with Heroku configuration. Another benefit is that all the code shared in GitHub will be free of any personal detail.

Using the “Add to Slack” copy-and-paste code supplied by Slack, I am able to install on my personal Slack team the /intro command, and start playing with it.

App Logic

When I type “/intro bla bla bla” in Slack, I get something like this redirected to my server

{ token: ‘XXX’,
team_id: ‘ERT34SDDF’,
team_domain: ‘my-team’,
channel_id: ‘CZESF234F’,
channel_name: ‘general’,
user_id: ‘GHJGHJ64S’,
user_name: ‘bob’,
command: ‘/intro-dev’,
text: ‘bla bla bla’,
response_url: ‘' }

The first step is to check that the token supplied matches the one in your record. If not, it might mean something fishy is going on.

Team, channel and user info are self-explanatory. Text is everything that was written after /intro, in plain text (in particular, Slack handles like @bob DO NOT get turned into the usual Slack format <@USDF45D|bob>.

Last point, the response_url is a hook allowing the app maker to reply up to 5 times in the next 30min. The default (simpler) method, if you don’t need a delayed response, is however to simply send a response to the HTTP request within 3 seconds. Here I send simply a summary of the request:

I add quickly filters for the requests /intro list (or status) and /intro help. If the text does not match these buckets, I parse it and check that the first two words are emails adresses — the rest is the “reason”. And everything that does not match this pattern gets defaulted to help.

If the two first words are emails, then I can send the emails to each person, asking if she’s OK with the intro.

The email contains links to /yes and /no routes, alongside with the ID of the Intro object and a random confirmation code.

If both people accept they are introduced one to each other.

That’s it!

Wrapping it up

You can install the app from here (Update: The app is not longer maintained and redirects to my main project, Smooz).

The code is open-sourced here.

— — — — —

Thanks for reading! If you have any feedback, thanks for sharing them in the comments. And if you liked the article, remember to click the green heart below so that others can discover it ;)

— — — — —