If this is the millionth article you've found on how to build a Slack bot with Node.js, I'm sorry. I've built a few Slack bots, some of which have launched on the Slack App Directory. I'm going to give you a no-bullshit tutorial on creating a Slack bot with Node.js. We'll build an internal tool that your team can use to get information about your customers using a slash command. I'm not going to teach you how to build a Slack app for the Slack App Directory. Set up Ngrok You need to use to connect your Slack workspace (on the internet) to your locally-running Slack bot (on your machine). It has a free plan, but the basic plan is affordable and extremely useful for building Slack bots. Ngrok : Ngrok exposes your machine to the internet, making it a potential attack vector. If you're building your Slack bot on your work machine, get Ngrok approved by your security team. Security note Create a Ngrok account and follow the set-up steps. When you're finished, expose a web server on port 8080: ngrok http 8080 This should produce the Ngrok console UI: ngrok by @inconshreveable Tunnel Status online Version 2.0/2.0 Web Interface http://127.0.0.1:4040 Forwarding http://92832de0.ngrok.io -> localhost:8080 Forwarding https://92832de0.ngrok.io -> localhost:8080 Connnections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00 If you're on the free Ngrok plan, . The forwarding URL is randomly generated, and will change when you restart Ngrok. don't close this terminal window Take note of the URL. In the example above, it is: . Forwarding https://92832de0.ngrok.io Set up your Slack app Before we start writing code, we need to create a Slack App. Navigate to . https://api.slack.com/apps?new_app=1 Select . From an app manifest Replace with your Ngrok forwarding URL in the App Manifest YAML file below. <NGROK_FORWARDING_URL> In the Ngrok example above, we would use . So, the example below would become: https://92832de0.ngrok.io redirect_urls https://92832de0.ngrok.io/slack/oauth_redirect Copy-paste the YAML contents in the section. Enter app manifest below _metadata: major_version: 1 minor_version: 1 display_information: name: NodeBot description: Our internal Slack bot. features: bot_user: display_name: NodeBot always_online: true slash_commands: - command: /customer url: <NGROK_FORWARDING_URL>/slack/events description: Get data about a customer usage_hint: /customer <customer id> should_escape: false oauth_config: redirect_urls: - <NGROK_FORWARDING_URL>/slack/oauth_redirect scopes: bot: - commands - chat:write - chat:write.public settings: org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: false App Manifest for your Slack bot 4. Select , then select . Next Create Scroll down to the **App credentials **section and take note of the following values: Client ID Client secret Signing secret Finally, install the app to your Slack workspace. Select on the left sidebar. Install App Select , and select on the installation page. Install to Workspace Allow Take note of the . Bot User OAuth Token Set up your Slack bot code Let's ensure your local environment is set up correctly. The dependencies for this Slack bot are as follows: node >=12.13.0 npm >=6.12.0 Start by creating a new directory for the Slack bot and initialising : npm mkdir slackbot-node cd slackbot-node npm init Follow the prompts (tip: hold down the Enter key). Let's install the project dependencies. Our main dependency is , the official Slack framework for building Slack apps with JavaScript. Bolt npm install --save @slack/bolt dotenv npm install --save-dev nodemon Add your environment variables Create a file. .env Add the following contents to your file, and add the values you took note of in the section. .env Set up your Slack app SLACK_CLIENT_ID=<YOUR SLACK CLIENT ID> SLACK_CLIENT_SECRET=<YOUR SLACK CLIENT SECRET> SLACK_SIGNING_SECRET=<YOUR SLACK SIGNING SECRET> SLACK_BOT_USER_TOKEN=<YOUR SLACKBOT USER TOKEN> SLACK_OAUTH_STATE_SECRET='my-state-secret' Create the bot server Create an file. This will be the entry point for our bot server. index.js Copy-paste the following code: require("dotenv").config(); const { App } = require("@slack/bolt"); const port = process.env.PORT || 8080; const app = new App({ token: process.env.SLACK_BOT_USER_TOKEN, signingSecret: process.env.SLACK_SIGNING_SECRET, }); // Slash command handler goes here. (async () => { await app.start(port); console.log(`🤖 Slack bot at your service (http://localhost:${port})`); })(); Check the server works by starting the bot server with . nodemon restarts the server whenever we edit our file nodemon index.js nodemon --exec node index.js You should get the following output: [nodemon] 2.0.13 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node index.js` 🤖 Slack bot at your service (http://localhost:8080) Add a slash command The file that we used to create our Slack app has already added a slash command for us; it's called . Whenever somebody in your Slack workspace types , Slack will send a POST request to your bot server; we need to program our bot server to respond correctly to the slash command. App Manifest /customer /customer /customer Add the following code to : index.js // Handle the /customer slash command app.command('/customer', async ({ command, ack, respond }) => { // Acknowledge command request await ack(); await respond('Slack bot at your service!'); }); Now, we can test the slash command in Slack. Type in Slack. This should yield the following result: /customer Getting customer data Finally, the juicy part. The method for getting customer data will vary based on your tech stack and where your customer data lives. Typically, you'll execute a database query here. For now, let's return some dummy user data. Format your response with the . Slack Block Kit Builder const customerData = { name: "Jane Doe", email: "jane@company.com", activeUsers: 10, plan: "Enterprise", totalSpend: "$1002.26", }; // Format the text however you like; Slack supports Markdown. const header = `*${customerData.name}* (${customerData.email})`; const body = `>${customerData.plan} plan\n>${customerData.activeUsers} users\n>${customerData.totalSpend} total spend`; const response = { response_type: "in_channel", // make the response public blocks: [ { type: "section", text: { type: "mrkdwn", text: `${header}\n${body}`, }, }, ], }; await respond(response); Let's run it in Slack and see the result. Type in Slack: /customer Building and maintaining internal Slack bots is a hassle. I built to help you rapidly create custom Slack bots. Write your internal script in your technology of choice, and Runtime handles the rest. Let me know what you think on . Runtime Twitter Also published on . https://blog.runtimehq.com/create-a-slack-bot-in-6-steps/