Build an infinitely scalable* Slack app in 5 minutes

avatar
Brian Leroux
February 07, 2018

Robots assembling cars Image courtesy gas2

Everyone’s favorite work messaging app — Slack — offers a powerful, open platform for developing rich applications in an increasingly important venue: where teams work and communicate together online. (This is why we started Begin!)

Amazon Web Services pioneered the relatively new concept — serverless application infrastructure — with their cloud functions product AWS Lambda.

Together these two platforms make for a delicious combination. Building software for Slack is an entirely web API-based endeavor, and Lambda makes for a superbly fast and flexible runtime for web services.

Ready to start delivering applications directly into the hub of the enterprise, using a new suite of technologies that enables you to focus solely on your application logic, without lengthy deploy times and little concern for scaling?

Let’s hit it!

This series of posts will walk through building for Slack with Architect, a framework for provisioning and managing serverless infrastructure we built for Begin.

  1. Stand up your infra and configure a new Slack app (this post!)
  2. Installing Slack apps with Add to Slack (coming soon!)
  3. Building super fast buttons and interactions inside of Slack
  4. Listening for Slack events

Prerequisites ✨

Before we get started make sure you have the following boxes checked:

You can learn more about getting setup at https://arc.codes/quickstart/setup

Step 1: Provisioning Your Serverless Infrastructure

If you know the right levers to pull, it’s not too difficult to set up Lambda behind API Gateway (Amazon’s service for building APIs) and DynamoDB (Amazon’s massively scalable schemaless database service), but using Architect makes the whole endeavor completely painless.

A. Create your project

So, let’s get started by initializing a vanilla NodeJS project in a terminal:

mkdir myproject
cd myproject
npm init -y
npm install @architect/workflows --save-dev
touch .arc

Then edit package.json to configure the following npm run commands:

// package.json

  "scripts": {
    "create": "AWS_PROFILE=xxx AWS_REGION=xxx arc-create",
    "deploy": "AWS_PROFILE=xxx AWS_REGION=xxx arc-deploy",
  }

Note: make sure you replace xxx values for AWS_PROFILE and AWS_REGION above with your AWS credentials and preferred deployment region (e.g. us-west-1).

We’ll use those npm run commands in a moment. But first we need to setup the AWS configuration manifest: .arc

RC files are an ancient UNIX convention for executable config files. That hidden .arc file we just created is a terse declarative markup language for defining cloud infrastructure agnostic of vendor arcana.

.arc syntax is quick to learn. Comments start with a #. Everything else defines infra. Edit the .arc file you created to read like this:

# this is an .arc file!
@app
hellobot
@html
get /        # displays Add to Slack
get /install # saves a bot token and redirects back to /
get /signin  # saves a user token and redirects back to /
@slack
bot          # sets up slack api urls

Here’s how this works:

  1. / — Your homepage
  2. /install — Your “Add to Slack” page, and…
  3. /signin — Your “Sign in with Slack” page

All told, from an Amazon Web Services perspective, this .arc file defines 14 Lambdas functions (7 for staging and 7 for production). These are all exposed as HTTP endpoints using API Gateway.

B. Provision your application

Provision the app by running npm run create and within a few minutes everything is ready to go (but not yet public).

Subsequent deployments to your shiny new serverless infrastructure happens via npm run deploy, and completes within seconds.

Pause: Woah! What Just Happened? 😲

Yes, there are many reasons to be excited about using Lambda functions to build Slack apps:

tl;dr: cloud functions shed the server metaphor by combining a natural syntax construct with smallest possible unit of compute infrastructure. This yields apps that are by default: more resilient, secure, faster, and reliable, at a lower cost.

FYI: Your new, generated HTTP Endpoints

Conveniently, Architect provisions both staging and production environments. For now let’s set up your app using just the staging environment.

You can find the URLs by navigating to API Gateway in the AWS Console, selecting the API you are interested in, selecting “Stages” and expanding the tree.

For reference, the generated routes will be something like these:

Generate routes

Staging and Production isolation means you setup two separate Slack apps. Seems a bit painful at first but as you iterate on your app you will find it is worth it.

In a future installment we’ll walk through configuring DNS so you have pretty URLs! 💕

Step 2: Create & configure your application in Slack

Now we need to create and configure your Slack application with these newly generated endpoints, and set up its permissions.

Navigate to https://api.slack.com and click on “Your Apps” → “Create New App”.

Create Slack App

Once you’ve created your app, then navigate to “Slash Command” in the left column, and click the “Create New Command” button.

The Request URL value should be your /staging/bot/slash path from the routes you just generated (so it should look something like https://xxx.execute-api.us-west-1.amazonaws.com/staging/bot/slash).

Create new command

To help make initial testing easier, you can install the app to your personal Slack workspace by navigating to “Basic Information” and clicking “Install App to Workspace”. (In a future post we’ll properly wire up the production install process with Add to Slack.)

Basic information

Step 3: Write a bit of code! ⌨

A. Slash command code

Back in your local project modify src/slack/bot-slash/index.js to read:

exports.handler = function slash(event, context, callback) {
  callback(null, {
    text: 'Hello!',
    attachments: [{
      text: 'Click the button',
      fallback: 'Click the button',
      callback_id: 'clicky',
      color: '#eheheh',
      actions: [{
        name: 'hello',
        text: 'hello',
        type: 'button',
        value: 'eh'
      }]
    }]
  })
}

View Source

Next, deploy the changes to staging by running npm run deploy. A full deployment (with zero downtime!) should complete within just a few seconds.

Now go test the app in Slack!

Super fast button test

B. Action handler code

Ok, time to make that button actually do something. Go back to the app configuration and select “Interactive Components”, then click “Enable Interactive Components”.

Set the Request URL to your /staging/bot/actions path. Don’t forget to hit “Save changes”!

Interactive components

Back in your local project, src/slack/bot-actions/index.js should read:

exports.handler = function actions(event, context, callback) {
    console.log(JSON.stringify(event, null, 2))
    callback(null, {text: "Hii from button press"})
}

The default button response is just a hardcoded value (for now). You can get very elaborate with buttons!

Summary

Nice work! You’re running a fully serverless Slack app on AWS! (And you didn’t even have to spend hours provisioning servers, setting up databases, and connecting everything together.)

In our next installment we’ll implement the Slack app installation flow with the Add to Slack button.

Going further

* Theoretically!