How to build and deploy a baseline Slack bot

Using Botkit, Node.js, Redis, Heroku & CloudFlare

Vijay Sundaram
11 min readJan 28, 2016

Bots are becoming the new thing and Slack, with its emerging bot development and distribution platform, is fueling the fire. I’ve been hacking up a Slack bot as a way to both learn more about how all this works and develop my web services chops. Now that I’ve got an alpha-grade Slack bot working, I thought I’d share a step-by-step walkthrough of what I did to build a baseline bot in case it’s helpful to designers and developers starting down the same path. I’ve also posted my code to Github and organized my commits around the key steps below so people can follow along in gory programming detail. Enjoy!

Define project outcomes

For this walkthrough, you’ll build what I call a “baseline” bot that’s shallow in functionality but wide in end-to-end completeness to the point where i) real-world teams can adopt and use it and ii) you can rapidly add and iterate functionality, interactions, etc. from there. So concretely, that means:

  • users find the bot at a brand-friendly home e.g. custom domain
  • users add the bot to their Slack team on their own e.g. “Add to Slack” button
  • users auth and use the bot application securely e.g. over HTTPS
  • data/state preserved across sessions, reboots, etc.
  • updates are developed and deployed with as little friction as possible

Choose technology stack

Our starting point is Botkit, a Slack-endorsed framework to simplify bot development. Among Botkit’s many wonderful qualities is built-in support for the plumbing required by the “Add to Slack” button and OAuth flow.

Botkit is only available for Node.js at the moment, so that makes picking an application runtime environment easy :) That said, Node.js is a natural fit for bot applications anyway given its real-time, event-driven properties.

The remaining technology choices – Redis for a persistent data store, Heroku for cloud hosting and Cloudflare for custom domain SSL – are a bit more interchangeable. I’m choosing these based on convenience and personal interest, but more sophisticated developers can easily adapt this guide for their own favorite database and ops setups instead.

With that out of the way, let’s dive in.

Create a new Slack bot application

First, create a new application in Slack. You can start the process from the developer applications page, which will lead you to form asking for the necessary details to register a new Slack application:

Note: For “Redirect URI(s)” use http://localhost:[port_number]/oauth and replace [port_number] with one of your choice. I’ll be using 4114 throughout this walkthrough but any valid and non-conflicting port number will do.

Once you submit this form, you should see a confirmation as well as a few additional details and options about your newly created application:

Note: This is where to locate your application client ID and secret. You’ll need to reference this in later sections.

Further down this page is a “Bot User” section where you need to configure your application to add a bot user:

One of the heavier decisions you have to make in this project is what to name your bot. Thankfully, unlike humans, you can change this easily. After naming and adding a bot user, this section should reflect the change:

Your bot application is now officially registered with Slack! You’re all done here, but keep this browser tab handy as you’ll need to refer to it later on.

Get a bot up and running with Botkit

Next, let’s implement a working bot. Here are the steps starting from a blank slate, with corresponding git commits showing code changes along the way:

  1. Install Node.js and npm if you haven’t already.
  2. Create a new directory for your project and name whatever you want.
  3. Make a copy of the example application slackbutton_bot.js from the Botkit Github repo and rename it to whatever you want. It’s an ideal starting point for the project because it minimally provides the plumbing to support the “Add to Slack” button and OAuth flow as well as multi-tenancy so your bot works across multiple teams. I’ve named this file ‘dotbot.js’, but just substitute your own filename throughout this walkthrough if different. [commit c75ab1]
  4. Set up the project for npm by a) creating a package.json file in your project directory that specifies a start script and a dependency on Botkit; and b) changing the Botkit module reference in dotbot.js from a local filepath to its module name. [commit 36c0ee0]
  5. Run the project by doing an ‘npm install’ in the project directory (which should download the Botkit module locally) and then ‘npm start’ (which should run the application). If all goes well, you should see an error logged to the console: “Error: Specify clientId clientSecret and port in environment”. That’s a good sign.
  6. The application expects values for clientId, clientSecret and port via environmental variables. If you recall, these values were set when creating a new Slack application. You provided a port number in the Redirect URI (for dotbot.js, it’s 4114), and Slack provided you a client ID and client secret after creating the application. Go gather these.
  7. There are a few different mechanisms for supplying these values to the app. For this walkthrough, I follow the approach detailed here, placing an ‘env.js’ file that sets these values in the project directory. I do *not* add or commit env.js to my project in order to keep the client secret private, it just exists locally on my development machine. [commit 495096e]
  8. In order to proceed, I had to comment out one of the handlers in the original Botkit example code to keep the application from hard crashing. I don’t know if it’s an issue on my end or Botkit’s but it’s not a show-stopper in building out the bot. [commit 9c891d0]
  9. Run the application again, and this time your bot should be up and running without any crashes or errors. You should also see a new folder “db_slackbutton_bot” in your project directory. This is a simple JSON-based local file store built into the Botkit framework and used by the application to persist auth and team information between sessions.

It’s alive! It’s not much to look at. In fact, there’s nothing to look at. Let’s change that.

Wire up a Slack button and authentication

Now that your bot is up and running, let’s set up a landing page so there’s a way to access and authorize it for a Slack team:

  1. Create an index.html for a landing page in your project directory. You can leave it blank to keep it simple or use your favorite lander template.
  2. Generate HTML code for an “Add to Slack” button, following the prompt from your application settings page on Slack. When doing so, make sure to set the ‘bot’ scope for your application. Add this code to index.html.
  3. Add a route to the application’s webserver to serve index.html. I set up dotbot.js to serve index.html for the homepage, but you can set the route however you want.

[code changes for steps 1–3 above are bundled into commit 5d23437]

That should do it! Let’s test it out. Restart your application and visit the landing page in your browser. The URL depends on the port and route you’ve set up (for dotbot.js it’s http://localhost:4114).

WARNING: At this stage, the authentication flow takes place over HTTP. For the reasonably paranoid, you should either set up an HTTPS-based redirect (not covered here) or skip the following steps on testing authentication until you reach the section on deploying to Heroku when you can test it over HTTPS.

The Slack bot authentication flow should look something like this:

add to Slack
select Slack team
authorize bot
do happy dance

Once authorized, your bot should send you a few friendly direct messages:

You now have a basic end-to-end system to access, authorize, and use your bot with Slack teams!

Go to town on bot logic

If you haven’t already, this is a good point to go to town building out your bot’s functionality and behavior. You can start by hacking on the boilerplate handlers in your application code or exploring the full library of Botkit APIs.

For the purposes of this walkthrough, I won’t go into any more detail about implementing bot features and interactions (perhaps in a future post) but of course this is the fun part. Whenever you’ve had your fill, the next step is deploying your bot application to the rest of the world.

Switch datastore to Redis (optional-ish)

Before deploying the bot application to Heroku, the hosting provider of choice in this walkthrough, you’ll need to update your application to use a different datastore. The one in place now, Botkit’s built-in JSON file store, won’t work because Heroku doesn’t persist locally written files.

Conveniently, Botkit supports different storage systems so the application logic is abstracted from the decision to use JSON-based files vs. Firebase vs. Redis, etc. Not sure this is an ideal medium- or long-term setup, but in the spirit of learning the ins and outs of Botkit let’s switch over to Redis.

I fumbled a bit with this as the Botkit docs are light on this topic, but eventually figured it out:

  1. Install Redis and get it running locally, if you haven’t already.
  2. Copy the redis_storage.js file from the Botkit Github repo and add it to your project directory. Botkit already has a few alternative storage provider implementations, including this one for Redis, which is nice.
  3. Add application code to instantiate a Redis store and configure Botkit to use it of the built-in JSON store. In dotbot.js I set the Redis URL to the default used by Redis, but you can change this per your own needs.
  4. Update package.json to include a dependency on the Redis client library.

[code changes for steps 1–4 above are bundled into commit 7a8ddb8]

Before testing the latest, clean up your project directory by deleting the node_modules and db_slackbutton_bot folders. Then run the application from scratch with ‘npm install’ and ‘npm start’. Your bot application should now be using Redis locally for its datastore!

Deploy application to Heroku

It’s time to deploy your bot so it can say hello to the world. Most web app developers are probably familiar with this general process, but for anyone newer to this and following along step by step, here’s how to update and deploy your bot application for Heroku:

  1. Create a Heroku account and install the Heroku Toolbelt.
  2. Install Git, initialize a repository in your project directory, and commit.
  3. Create a new Heroku app with ‘heroku create’ (from project directory).
  4. In the Heroku Dashboard, add the Heroku Redis add-on (or set up whatever datastore you decided to use).
  5. Update the bot application to use the Redis URL provided by Heroku via the REDIS_URL environment variable. The way I do this in dotbot.js is such that if this value is not provided, it defaults to the local Redis URL. This way I can run the same code my local machine and Heroku.
  6. Remember that the application uses a local env.js file to get values for the client ID, client secret and port, and that this file is not committed to the repo (to keep the client secret private). When deploying in Heroku, you can supply these environmental variables through the Heroku Dashboard > [app name] > Settings > Config Variables section. Add key-value pairs here for clientId and clientSecret, but not for port which is handled differently...
  7. Similar to the Redis URL in (5), the bot application needs to use the port provided by Heroku via the PORT environment variable. Again, the way I do this in dotbot.js is such that if the Heroku environment variable is not provided, the application uses the value supplied from the local env.js file. Frankly this feels a little hacky, but it does the job for running the same code locally and in Heroku without exposing the client secret.
  8. Push and deploy your bot application to Heroku with ‘git push heroku master’ (from project directory).
  9. Before using your deployed bot application, update the Redirect URI in your Slack application settings to use the hostname of your new Heroku app e.g. https://your-heroku-app-name.herokuapp.com/oauth.

[code changes for steps 1–9 above are bundled into commit 53e72c7]

Note: You can set up and test all this at no cost using the free tiers for Heroku dynos and the Heroku Redis add-on, but unfortunately it’s not enough for production. The free tier dynos make your bot narcoleptic, forcing it to sleep after 30min of inactivity and for 6h in a 24h period :-/ You’ll want to upgrade to the “Hobby” plan ($7 per dyno/month) to keep the bot operational 24-7. Or just find a cheaper hosting solution, which is on my to do list.

Awe. Some. Sauce. Users can now access, authenticate, and use your bot application securely over HTTPS on the public interwebs! And you can now rapidly iterate on the bot just by committing changes to git and pushing to Heroku to deploy.

What more could you ask for? Well, actually…

Use a custom domain

You’ve come this far in building a publicly hosted Slack bot. It deserves a nicer home than a rando hosting URL. Thankfully Cloudflare and Heroku make it easy to set this up, with the added bonus of free SSL. Here’s how:

  1. Buy a domain for your bot at your favorite (or hated) domain registrar.
  2. Follow this excellent guide to configure Cloudlare and Heroku over HTTPS and set it up for your new domain name.
  3. Remember to go back and update your Slack application’s Redirect URI to use your custom domain e.g. https://my-bot.com/oauth.

Wrap up

Phew! That about does it for now. There’s still so much to cover, not least being a bunch of super-interesting user experience questions that’ve come up in building my Slack bot, but that’ll have to wait for a future post. In the meantime, I hope this helps aspiring bot designers and developers get started. Please don’t be shy about contacting me with feedback, questions, ideas, or opportunities to collaborate!

--

--