{"id":16696892,"url":"https://github.com/seratch/apidays-workshop-2020","last_synced_at":"2026-04-01T21:48:49.458Z","repository":{"id":139893961,"uuid":"288429045","full_name":"seratch/apidays-workshop-2020","owner":"seratch","description":"Apidays: Slack app workshop","archived":false,"fork":false,"pushed_at":"2020-09-15T02:11:30.000Z","size":51,"stargazers_count":4,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-28T00:22:46.989Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://git.io/apidays-slack","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seratch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-18T10:49:15.000Z","updated_at":"2022-02-18T12:25:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"7186d353-0f33-4993-961b-a691883dd7de","html_url":"https://github.com/seratch/apidays-workshop-2020","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/seratch/apidays-workshop-2020","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fapidays-workshop-2020","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fapidays-workshop-2020/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fapidays-workshop-2020/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fapidays-workshop-2020/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seratch","download_url":"https://codeload.github.com/seratch/apidays-workshop-2020/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fapidays-workshop-2020/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T17:45:10.775Z","updated_at":"2026-04-01T21:48:49.443Z","avatar_url":"https://github.com/seratch.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Welcome to Slack App Development!\n\nThis repository is the workshop material for [Apidays live Singapore](https://www.apidays.co/singapore/) and [Apidays live Australia](https://www.apidays.co/australia/). If you're not an attendee of the workshop, don't worry! You can try this sample project just by reading this.\n\n## Go to **git.io/apidays-slack**\n\nThis project template is available at **git.io/apidays-slack** (https://github.com/seratch/apidays-workshop-2020). Use the shortened URL for sharing this material with others!\n\n## The App We're Going to Build - Helpdesk App\n\nIn this workshop, we're going to build a **helpdesk workflow app** from scratch. Building the app helps us learn how to start Slack App development and utilize the latest Slack Platform features.\n\nHere is the quick demo of the complete version of the helpdesk workflow:\n\n### Run a Global Shortcut\n\nWhen an end-user clicks a **shortcut** from the text composer (or the search bar), a **modal window** pops up.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/93039835-80c89880-f683-11ea-8cc7-3a7289c61101.gif\" width=600\u003e\n\n### Multiple Steps in a Modal\n\nWhen the user selects a category from the select menu, **the modal immediately transforms itself** to show input fields for the chosen category. Also, **\"Back\" button** in the modal allows the user to go back to the initial step.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/93039831-79a18a80-f683-11ea-8474-51a85c2cdc6f.gif\" width=600\u003e\n\n### Custom Validations in a Modal\n\n\nThe app applies **custom input validation rules** for the title and due-date inputs.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/93039823-727a7c80-f683-11ea-93f3-9ae306b316fa.gif\" width=600\u003e\n\n### Send Notifications\n\nWhen the app receives a valid data submission from the user, the app **sends notifications** to the helpdesk team's channel, the DM with the submitter, and the DM with the approver (only for mobile device requests). \n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/93039844-8625e300-f683-11ea-9331-a6ce591298dd.gif\" width=600\u003e\n\n### Refresh Home Tabs\n\nIn addition, the app updates **Home tab** for the submitter with the up-to-date list of the person's submissions.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/93040135-38f64100-f684-11ea-85b9-dc78a16e7a3f.gif\" width=600\u003e\n\n## The Slack Platform Features\n\nWe'll meet the above requirements by leveraging many of the latest Slack Platform features. We'll learn effective ways to take advantage of [Block Kit](https://api.slack.com/block-kit), [Global Shortcuts](https://api.slack.com/interactivity/shortcuts), and [Modals](https://api.slack.com/surfaces/modals).\n\n* [Block Kit](https://api.slack.com/block-kit): Block Kit is the Slack's UI framework for building an rich user interface. From a Slack app developer perspective, it is just a kind of JSON data structure to comply with. Slack properly renders your specifically structured JSON for both desktop and mobile.\n* [Global Shortcuts](https://api.slack.com/interactivity/shortcuts): A Global Shortcut is a quick and easy way to start a workflow from anywhere in Slack. Users can access global shortcuts from either the menu in text composer or search bar. Try a built-in one to learn how it works.\n* [Modals](https://api.slack.com/surfaces/modals): A modal is a popover window built with Block Kit components. You use this for collecting user inputs or displaying information in an organized way. A modal can have multiple steps in its flow.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19658/90348199-cf2c4c80-e06f-11ea-81a5-ad7be2ddcda3.gif\" height=400\u003e\n\n## Bolt for JavaScript\n\nWe're going to use [Bolt for JavaScript](https://slack.dev/bolt-js/), a Slack app framework optimized for taking full advantage of the Platform features. With Bolt, you won't be bothered by Slack-specific non-functional requirements:\n\n* Verify requests from Slack for security (Your API endpoint is exposed to the internet. That means not only Slack, but any random clients may try to send requests to your endpoint. So, it's highly recommended to distinguish Slack's requests from others.)\n* Parse a variety of payloads (For historical reasons, the data structure of payloads varies among features.)\n* Dispatch requests to their right code path (similarly to well-designed full-stack Web app frameworks)\n* Avoid infinite loop errors by reacting to events triggered by the app itself (particularly when using Events API)\n* Pick up the right access token for an incoming request\n\nAs Bolt takes care of these things, your Slack app development becomes even more productive.\n\n## All The Steps to Build This App\n\n### Get the Project Template\n\nAccess **git.io/apidays-slack**!\n\n```bash\ngit clone git@github.com:seratch/apidays-workshop-2020.git\ncd apidays-workshop-2020/\nnode --version # need to be v10.13 or higher\nnpm i # install dependencies\ncode . # Open the project with Visual Studio Code\n```\n\n### Create a New Slack App\n\nVisit https://api.slack.com/apps to create a new Slack App configuration.\n\n[Signing in](https://slack.com/signin) to the Slack workspace you're going to use for development in the browser is required.\n\n### Add Required Bot Token Scopes\n\nGo to the **OAuth \u0026 Permissions** page and add the following **Bot Token Scopes** to the app.\n\n* [`commands`](https://api.slack.com/scopes/commands) for creating a Global Shortcut\n* [`chat:write`](https://api.slack.com/scopes/chat:write) for [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) API calls\n* [`chat:write.public`](https://api.slack.com/scopes/chat:write.public) for [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) API calls in public channels where the bot user is not yet invited\n* [`im:write`](https://api.slack.com/scopes/im:write) for [`conversations.open`](https://api.slack.com/methods/conversations.open) API calls\n\n### Give Your Bot User a Relevant Name\n\nThe Slack App's name automatically determines the default bot user name. If you prefer a different name over the name automatically set, go to **App Home** page and change it. As a bot user name is user-facing, making it nice is crucial for better user experiences.\n\n### Install The App Onto Your Development Workspace\n\nAs long as you use this app only in its development workspace, you don't need to implement [the standard OAuth flow](https://api.slack.com/authentication/oauth-v2) for acquiring OAuth access tokens. You can go with the simplified way offered by the Slack Platform. Go to the **Install App** page and just click the install button and complete the OAuth flow. You'll use the **Bot User OAuth Access Token** when booting your Bolt app.\n\nIf you're interested in distributing your app to multiple workspaces, refer to [the Bolt JS's guide](https://slack.dev/bolt-js/concepts#authenticating-oauth).\n\n### Run the Bolt App\n\nAll the steps to follow for booting your Bolt app are:\n\n* Create `.env` file at the root directory of this project\n* Make sure if you're using Node.js 10.13 or higher (`node --version`)\n* Run `npm install` to fetch all required dependencies\n* Run `npm run local` to start the local app\n* Install ngrok if you don't have yet - https://ngrok.com/\n* Open another terminal and run `ngrok http 3000` to establish a public endpoint\n\n#### Place .env and Save Your Credentails\n\n```\nSLACK_BOT_TOKEN=xoxb-111-111-xxx\nSLACK_SIGNING_SECRET=xxx\n```\n\n#### Run the Local App\n\nThe procedure is actually quite simple. Run the following commands.\n\n```bash\nnode --version # should be v10.13.0 or higher\nnpm install\nnpm run local # This starts an app at http://localhost:3000/slack/events\n```\n\n#### Run ngrok for Forwarding Slack Requests To Your Local App\n\nIf you don't have [ngrok](https://ngrok.com/), download it.\n\n```bash\n# Check if the local app is running\ncurl -I -XPOST http://localhost:3000/slack/events # You should get HTTP/1.1 401 Unauthorized\n\n# on another terminal\n./ngrok http 3000\n\n# if you're a paid user\n./ngrok http 3000 --subdomain {whatever-you-want}\n\n# You can verify if it's working by the following on yet another terminal:\ncurl -I -XPOST https://{your random subdomain here}.ngrok.io/slack/events # You should get HTTP/1.1 401 Unauthorized\n```\n\n### Set Request URL and add a Global Shortcut\n\n* Visit the Slack App configuration page (https://api.slack.comc/apps) and choose your app\n* Go to the **Interactivity \u0026 Shortcuts** page\n* Turn on the Interactivity feature\n* Set `https://{your random subdomain here}.ngrok.io/slack/events` as the Request URL\n* Create a new Shortcut (Global -\u003e Callback ID: `new-helpdesk-request`)\n* Click the **Save Changes** button at the bottom\n\n### Implement Listeners in Your Bolt App\n\nCheck the [./src/solution.js](./src/solution.js) to know the complete version of the app.\n\n* Add a [Global Shortcut listener](https://slack.dev/bolt-js/concepts#shortcuts) for callback_id: `new-helpdesk-request`\n* Add an [Action listener](https://slack.dev/bolt-js/concepts#action-listening) for action_id: `helpdesk-request-modal-category-selection`\n* Add an [Action listener](https://slack.dev/bolt-js/concepts#action-listening) for action_id: `helpdesk-request-modal-reset`\n* Add a [View Submission listener](https://slack.dev/bolt-js/concepts#view_submissions) for callback_id: `helpdesk-request-modal`\n\n#### Tip: Block Kit Preview Tool\n\n[Block Kit Builder](https://api.slack.com/block-kit-builder) is a preview tool in the browser to see how your `blocks` look like in Slack. I recommend checking the validity and the appearance of your `blocks` using this tool before embedding them into your app.\n\n* [Step 1 modal in Block Kit Builder](https://app.slack.com/block-kit-builder#%7B%22type%22:%22modal%22,%22callback_id%22:%22helpdesk-request-modal%22,%22title%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Helpdesk%20Request%22%7D,%22close%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Close%22%7D,%22blocks%22:%5B%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22:wave:%20Select%20a%20category.%22%7D%7D,%7B%22type%22:%22actions%22,%22elements%22:%5B%7B%22type%22:%22static_select%22,%22action_id%22:%22helpdesk-request-modal-category-selection%22,%22options%22:%5B%7B%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Laptop%22%7D,%22value%22:%22laptop%22%7D,%7B%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Mobile%22%7D,%22value%22:%22mobile%22%7D,%7B%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Other%22%7D,%22value%22:%22other%22%7D%5D%7D%5D%7D%5D%7D)\n* [Step 2 modal in Block Kit Builder](https://app.slack.com/block-kit-builder#%7B%22type%22:%22modal%22,%22callback_id%22:%22helpdesk-request-modal%22,%22private_metadata%22:%22%7B%5C%22category%5C%22:%5C%22mobile%5C%22%7D%22,%22title%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Helpdesk%20Request%22%7D,%22submit%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Submit%22%7D,%22close%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Close%22%7D,%22blocks%22:%5B%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22You're%20making%20a%20request%20on%20your%20mobile%20devices.%22%7D,%22accessory%22:%7B%22type%22:%22button%22,%22action_id%22:%22helpdesk-request-modal-reset%22,%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Back%22%7D,%22value%22:%221%22%7D%7D,%7B%22type%22:%22input%22,%22block_id%22:%22title%22,%22label%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Title%22%7D,%22element%22:%7B%22type%22:%22plain_text_input%22,%22action_id%22:%22element%22,%22initial_value%22:%22Mobile%20Device%20Replacement%22%7D%7D,%7B%22type%22:%22input%22,%22block_id%22:%22os%22,%22label%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Mobile%20OS%22%7D,%22element%22:%7B%22type%22:%22static_select%22,%22action_id%22:%22element%22,%22placeholder%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Select%20an%20item%22%7D,%22options%22:%5B%7B%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22iOS%22%7D,%22value%22:%22ios%22%7D,%7B%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Android%22%7D,%22value%22:%22android%22%7D%5D%7D%7D,%7B%22type%22:%22input%22,%22block_id%22:%22approver%22,%22label%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Approver%22%7D,%22element%22:%7B%22type%22:%22users_select%22,%22action_id%22:%22element%22,%22placeholder%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Select%20your%20approver%22%7D%7D%7D,%7B%22type%22:%22input%22,%22block_id%22:%22due-date%22,%22element%22:%7B%22type%22:%22datepicker%22,%22action_id%22:%22element%22%7D,%22label%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Due%20date%22,%22emoji%22:true%7D%7D%5D%7D)\n\n## Recap\n\n* Create a Slack app configuration at https://api.slack.com/apps\n  * Signing in with your Slack workspace account is required\n* Configure the Slack app with sufficient permissions\n  * Go to the \"OAuth \u0026 Permissions\" page and add bot token scopes\n  * Turn the features you use on (Interactivity, Events Subscriptions, Home tab, and so on)\n* Install the app onto its Development Slack Workspace\n  * Grab the \"Bot User OAuth Access Token\" starting with \"xox**b**-\"\n* Create a Bolt app\n  * Set env variables - `SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`\n  * Start the app (`app.start()`)\n  * By default, Bolt apps receive requests coming to `POST http://localhost:3000/slack/events`\n* Have a public endpoint to receive requests from Slack\n  * You may use ngrok or similar for it (`ngrok http 3000`)\n* Add listeners for incoming requests\n  * Check ngrok access logs (`http://localhost:4040`)\n  * Check the error messages in stdout\n  * Read [the Bolt for JS documents](https://slack.dev/bolt-js)\n* Have fun with Slack app development \n\n# License\n\nThe MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseratch%2Fapidays-workshop-2020","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseratch%2Fapidays-workshop-2020","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseratch%2Fapidays-workshop-2020/lists"}