Creating a basic Slack app
Tags: node, slack, bolt
Published: 2021-06-15 05:53:54

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwysuawi5izgpvmbfkhl.png)

Slack has done a good job of documenting how to create a basic Slack app to get you over the configuration hump.  And there are some handy simple examples on Glitch which save you from having to create your own server to host the backend code.  The following blog post captures my notes on how to do the same on my local Mac using NodeJS, Slack's [Bolt](https://slack.dev/bolt-js/concepts) JavaScript framework, and ngrok to expose the application to the internet.

There's nothing revolutionary in the following blog post, this is just a documentation exercise so I don't have to keep remembering every step!

# Setup ngrok

Mac install instructions:
(1) Download ngrok (https://ngrok.com/download)
(2) Unzip the ngrok zip file, and drag and drop the resulting ngrok file to our user's Mac Application folder
(3) Setup a symbolic link so ngrok can be accessed across our system:
`cd /usr/local/bin`
`ln -s /Applications/ngrok ngrok`
(4) Start ngrok:
`ngrok http 5000`

Note we're forwarding to port 5000 in this example.  Change this to whatever we want, but record the value.  This will be important when we create the backend NodeJS code for the application shortly.

From the ngrok's output note the https:// forwarding address.  Record this, you will need this shortly.  The following is an example output:
```
Session Status                online                                                                
Session Expires               1 hour, 59 minutes                                                    
Version                       2.3.40                                                                
Region                        United States (us)                                                    
Web Interface                 http://127.0.0.1:4040                                                 
Forwarding                    http://165a936dd19b.ngrok.io -> http://localhost:5000                 
Forwarding                    https://165a936dd19b.ngrok.io -> http://localhost:5000                
```                                                                                                    
# Configure the app at api.slack.com

Slack's [api.slack.com](https://api.slack.com) website is where we setup and maintain the configuration of our application such as the application name, privileges, and the URLs for Slack to call our backend NodeJS application that we will create shortly.

In the following example we will use Slack's new beta [manifest file](https://api.slack.com/reference/manifests) format to setup the basic configuration.

(5) Create or reuse our own Slack account and Slack workspace
(6) Login to [api.slack.com](https://api.slack.com) using our Slack account
(7) Select *_Your Apps_* button top right, then the *_Create an App_* button centre of the screen
(8) Select *_From an app manifest_*
(9) Step 1 of 3: Select your workspace
(10) Step 2 of 3: Copy in the following manifest file:
```yaml
_metadata:
  major_version: 1
  minor_version: 1
display_information:
  name: ScratchSlackApp
features:
  app_home:
    home_tab_enabled: false
    messages_tab_enabled: true
    messages_tab_read_only_enabled: false
  bot_user:
    display_name: ScratchSlackApp
    always_online: false
oauth_config:
  scopes:
    bot:
      - chat:write
      - im:write
      - im:history
settings:
  event_subscriptions:
    request_url: https://165a936dd19b.ngrok.io/slack/events
    bot_events:
      - message.im
  org_deploy_enabled: false
  socket_mode_enabled: false
```
Update the *_request_url_* with the ngrok https:// forwarding address from earlier.

(11) Continue with step 3 of 3: Select *_Create_*

(12) The website will now take us to the settings for the application.  Ensure the *_Basic Information_* settings page is selected, then within this page under the *_Install your app_* heading, select the *_Install to Workspace_* button.
(13) In the proceeding permissions page, select the *_Allow_* button.  This step will make the application available to our user in the Slack client under the Apps section.  At this stage the application has no backend logic so the app will do nothing, we will create this next.
(14) Returning to the *_Basic Information_* setting page, navigate down to the *_App Credentials_* section and *_Show the Signing Secret_* (commonly known as the 'Slack Signing Secret').  Record this value, we will need this value in a moment.
(15) Select the *_OAuth & Permissions_* features page, and note the *_Bot User Oauth Token_*.  Also record this value, you will need this in a moment.

> ngrok note: if you stop and restart ngrok, assuming you are using the free version which does not provide a static URL, the ngrok URL will change each restart.  To update the above request_url in the Slack app, visit the *_Event Subscriptions_* page and update the *_Request URL_*.  However note if you manually update this value (rather than defining it through the manifest file when you first create the app), Slack will attempt to check that the URL is live and running.  As such you need to create and run the Slack application first as defined in the next section before you can update the URL.

## Create the NodeJS backend application

On completing the above steps, we are now ready to create the backend NodeJS application that will listen and respond to events sent by the user via the Slack client, relayed through Slack, as configured in the above settings.

In other words if the user types a message into our Slack app in the Slack client, the message will be relayed from the Slack client to Slack's own servers, whereupon Slack will look up the request_url defined above, and send the message to the defined URL where our Slack code is running and can respond.

(16) On our local Mac:
`cd ~/Desktop`
`mkdir ScratchSlackApp`
`cd ScratchSlackApp`
`npm init -y`

(17) In the same directory open the generated *_package.json_* file in our favourite text editor and overwrite the complete file with the following contents:
```json
{
  "name": "scratchslackapp",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@slack/bolt": "^3.4.0",
    "dotenv": "^10.0.0"
  }
}
```
(18) Still within our favourite text editor, create a new file *_app.js_* in the same directory and copy in the following code:
```javascript
const { App, ExpressReceiver } = require('@slack/bolt');

require('dotenv').config();

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET
});

app.message(async ({ body, message, context, say }) => {
  try {
    if (body.event.type === 'message' && message.text !== undefined) {
      say('Hi!');
    }
  } catch (error) {
    say(error.message);
  }
});

(async () => {
  await app.start(process.env.PORT);
  console.log('⚡️ Bolt app is running on port ' + process.env.PORT + '!');
})();
```
The basic code here:

+ *_New App()_* sets up a Slack app using the Slack Bolt JavaScript framework.  This includes all the magic for setting up the required HTTP listeners, that will receive HTTP/HTTPS requests sent from Slack to our code via the request_url we configured in the manifest file earlier.

+ The *_app.message()_* handler receives 'text' messages from Slack which we can then respond to.

+ The final *_app.start()_* call in the async block starts the Bolt server, including the HTTP listeners.

(19) Note the 3 *_process.env_* calls to *_PORT, SLACK_BOT_TOKEN & SLACK_SIGNING_SECRET_*.  These are the 3 values we asked you to record earlier.  To set these in our favourite text editor create an additional file *_.env_* in the application's base directory, and copy in the values we recorded:
```
PORT=5000
SLACK_BOT_TOKEN=xoxb-123472270484-1234804366771-cEXFXx0jgAA9bnAAaS16fvgc
SLACK_SIGNING_SECRET=263b7d12a7ccaea3f838f3ef123062ef
```
The above values are examples only.

(20) Finally on the command line we need to install the libraries/dependencies defined in the *_package.json_* file then run our application:

`npm install`
`node app.js`