<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tomomi Imura 🐱 </title>
    <description>The latest articles on DEV Community by Tomomi Imura 🐱  (@girlie_mac).</description>
    <link>https://dev.to/girlie_mac</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F109247%2Fb7da1ba7-9b52-4ff1-899c-ea16990589c0.jpg</url>
      <title>DEV Community: Tomomi Imura 🐱 </title>
      <link>https://dev.to/girlie_mac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/girlie_mac"/>
    <language>en</language>
    <item>
      <title>Customizing F5 Debugging in Teams Toolkit for VS Code</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Mon, 31 Oct 2022 19:16:52 +0000</pubDate>
      <link>https://dev.to/azure/customizing-f5-debugging-in-teams-toolkit-for-vs-code-2d9j</link>
      <guid>https://dev.to/azure/customizing-f5-debugging-in-teams-toolkit-for-vs-code-2d9j</guid>
      <description>&lt;p&gt;Earlier this year, Teams Toolkit has introduced a few new features that have been added in the latest Toolkit to improve your &lt;a href="https://dev.to/azure/debugging-teams-app-locally-with-teams-toolkit-2b67"&gt;debugging experience&lt;/a&gt;, including Prerequisite Checker and Customizing Debug Settings. &lt;/p&gt;

&lt;p&gt;With the latest Toolkit in v.4.1.0 and greater, you can now customize the debugging experiences even more!&lt;/p&gt;

&lt;p&gt;If this is the first time with Teams Toolkit, please check out these tutorials first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/microsoft365dev/beginners-crash-course-to-build-apps-for-teams-using-teams-toolkit-for-visual-studio-code/" rel="noopener noreferrer"&gt;Beginners’ crash course to build apps for Teams using Teams Toolkit for Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/girlie_mac/roll-a-dice-building-a-command-bot-for-microsoft-teams-using-team-toolkit-v4-with-vs-code-3e3b"&gt;Roll A Dice! - Building a Command Bot for Microsoft Teams Using Team Toolkit v4 with VS Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🐛 Debugging Experiences in Teams Toolkit
&lt;/h2&gt;

&lt;p&gt;Debugging in VS Code is casually referred to as &lt;strong&gt;F5&lt;/strong&gt; among developers, is one of the key features of Visual Studio Code, and this built-in debugger helps accelerate your edit, compile, and debug loop.&lt;/p&gt;

&lt;p&gt;When you created any project with Teams Toolkit in VS Code, you also use this F5 debugger to run the code. While you are waiting, Teams Toolkit runs various process, check prerequisites, and output the results like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsep76i89kvj14mk7oc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsep76i89kvj14mk7oc3.png" alt="Screenshot of debug output from Teams Toolkit in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Output section, you can view what the debugger is doing. In this screenshot, you can see a checklist, including whether you have a specific Node.js, your M365 account status, etc. &lt;/p&gt;

&lt;p&gt;So, where these tasks and the checklist are defined? It is in &lt;strong&gt;.vscode&lt;/strong&gt;/&lt;strong&gt;tasks.json&lt;/strong&gt; in the generated project, and you can customize in the way you want. So let's take a look at some customization examples for both a &lt;em&gt;tab app&lt;/em&gt; and &lt;em&gt;bot app&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗂 Customizing tasks.json for Tab Apps
&lt;/h2&gt;

&lt;p&gt;First, let's create a new app by choosing the SSO-enabled Tab from the menu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvx95ythm922yvux2h13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvx95ythm922yvux2h13.png" alt="Screenshot of app creation in Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the project is generated, open &lt;strong&gt;.vscode&lt;/strong&gt;/&lt;strong&gt;tasks.json&lt;/strong&gt; and see what are defined:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnfrj6jppxcy4b1snhnx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnfrj6jppxcy4b1snhnx.png" alt="Screenshot of Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may want to try debugging and see how each item defined in the &lt;strong&gt;tasks.json&lt;/strong&gt; runs and display in the Output by default:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wce7tbl2c0lml6fs4x5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wce7tbl2c0lml6fs4x5.png" alt="Screenshot of Teams Toolkit Debug Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, see how to customize the debugging flow by editing the &lt;strong&gt;tasks.json&lt;/strong&gt; file. &lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Customizing Prerequisites
&lt;/h3&gt;

&lt;p&gt;For example, if you want to skip certain processes, such as checking prerequisites and installing npm packages, just comment out where they are defined in &lt;code&gt;"tasks"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start Teams App Locally&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependsOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;//"Validate &amp;amp; install prerequisites",&lt;/span&gt;
      &lt;span class="c1"&gt;//"Install npm packages",&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up tab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up SSO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Build &amp;amp; upload Teams manifest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start services&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can select prerequisites validation independently. Scroll down to the next object in JSON then editing these lines. For example, if you want to skip checking if Node.js is installed, comment the line out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Validate &amp;amp; install prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug-check-prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;//"nodejs",&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m365Account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devCert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;portOccupancy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try running F5 and see if the processes are skipped.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛎 Customizing npm Commands
&lt;/h3&gt;

&lt;p&gt;Also, you can customize &lt;code&gt;npm install&lt;/code&gt; commands by adding an optional argument, for example, &lt;code&gt;--force&lt;/code&gt; to force npm to fetch remote resources even if a local copy exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Install npm packages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug-npm-install&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;projects&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cwd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;${workspaceFolder}/tabs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npmInstallArgs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--no-audit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--force&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// added!&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛳 Changing Service Port
&lt;/h3&gt;

&lt;p&gt;Tabs in tab apps are basically web pages embedded in Teams client, and they run on a specific port when you debug locally. By default, it is set &lt;code&gt;53000&lt;/code&gt; and the web portion of your app can be debugged in &lt;code&gt;https://localhost:53000&lt;/code&gt;. The Toolkit debugger checks if the port is available.&lt;/p&gt;

&lt;p&gt;If you would like to change the port, you need to edit two places in the JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Validate &amp;amp; install prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug-check-prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nodejs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m365Account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devCert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;portOccupancy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;portOccupancy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="mi"&gt;33000&lt;/span&gt; &lt;span class="c1"&gt;// was 53000&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up tab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug-set-up-tab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;baseUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://localhost:33000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// was 53000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can customize more by deleting/commenting out lines, edit values, and add values in the JSON file. &lt;/p&gt;

&lt;p&gt;Some values are commented out by default, such as SSO setup, so you can enable some by uncommenting the lines too. Just customize as your app needs!&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Customizing tasks.json for Bots
&lt;/h2&gt;

&lt;p&gt;Next, let's take a look at a bot app. You can customize the tasks in the way I showed you for tab apps (such as the prerequisites checks), except there are some differences between tabs and bots.&lt;/p&gt;

&lt;p&gt;Let's create a new command bot and see how the tasks are different. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubd43bamo9xgnl8ewesm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubd43bamo9xgnl8ewesm.png" alt="Screenshot of Teams Toolkit in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the file at &lt;strong&gt;.vscode&lt;/strong&gt; &amp;gt; &lt;strong&gt;tasks.json&lt;/strong&gt;. You can see some tasks are different from the tab app. There are bot-specific tasks including, "Set up bot" and "Start local tunnel":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start Teams App Locally&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependsOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Validate &amp;amp; install prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Install npm packages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start local tunnel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Build &amp;amp; upload Teams manifest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start services&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependsOrder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sequence&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run the debugger, you can see the process in the Output pane, in the same way you saw for the tab app.&lt;/p&gt;

&lt;p&gt;Customization can be done in the same manner, so if you want to skip certain tasks, you can comment the lines out.&lt;/p&gt;

&lt;p&gt;Next, we are going to take a look at the bot-specific tasks and settings. &lt;/p&gt;

&lt;h3&gt;
  
  
  🛳 Changing Bot Service Port
&lt;/h3&gt;

&lt;p&gt;Bots use ports to run bot services, where tabs run web services.&lt;/p&gt;

&lt;p&gt;Just like the port for tabs you just learned, you can manually change the &lt;code&gt;"PortOccupancy"&lt;/code&gt;. Let's change the bot service port to something different from the default, 3978:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;portOccupancy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="mi"&gt;4978&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// bot service port. By default it it 3978&lt;/span&gt;
    &lt;span class="mi"&gt;9239&lt;/span&gt; &lt;span class="c1"&gt;// bot inspector port for Node.js debugger&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you also need to change this in &lt;code&gt;"ngrokArgs"&lt;/code&gt; setting, as well as in another file. You can search and replace the port number:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flya3xwowytx61sebrai6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flya3xwowytx61sebrai6.png" alt="Screenshot of Teams Toolkit in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🏔 Using Your Own Local Tunneling Service
&lt;/h3&gt;

&lt;p&gt;By default, the local tunnel is created with a tool called, &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;, however, you can replace it with something else you prefer.&lt;/p&gt;

&lt;p&gt;To make the change, first, comment out the "Start local tunnel" from the tasks' &lt;code&gt;"dependsOn"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start Teams App Locally&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependsOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Validate &amp;amp; install prerequisites&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Install npm packages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;//"Start local tunnel",&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Build &amp;amp; upload Teams manifest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start services&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, change the &lt;code&gt;"botMessagingEndPoint"&lt;/code&gt; to your own tunnel URL at the bot setup task. I want to use my &lt;strong&gt;contoso&lt;/strong&gt; service, so I am using the preferred path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set up bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug-set-up-bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;botMessagingEndpoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://contoso.com/api/message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Contoso is a fictional service, in case you are not familiar with this Microsoft's favorite fake company name&lt;/em&gt; 😉&lt;/p&gt;

&lt;p&gt;Run F5 and see the changes.&lt;/p&gt;




&lt;p&gt;I didn't cover every possible task scenarios here, but I hope you found the article helpful for debugging your Teams apps. Please don't hesitate to drop your comments and feedback here.&lt;/p&gt;

&lt;p&gt;Mahalo and see you soon 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/teams-toolkit-fundamentals?WT.mc_id=m365-79237-timura" rel="noopener noreferrer"&gt;Teams Toolkit documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview/?WT.mc_id=m365-79237-timura" rel="noopener noreferrer"&gt;Get started with Microsoft Teams platform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📢 Shoutout
&lt;/h3&gt;

&lt;p&gt;Teams Toolkit Engineering team, especially Ji Dong 🌟&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>msteams</category>
      <category>vscode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Roll A Dice! - Building a Command Bot for Microsoft Teams Using Team Toolkit v4 with VS Code</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Thu, 20 Oct 2022 20:50:27 +0000</pubDate>
      <link>https://dev.to/azure/roll-a-dice-building-a-command-bot-for-microsoft-teams-using-team-toolkit-v4-with-vs-code-3e3b</link>
      <guid>https://dev.to/azure/roll-a-dice-building-a-command-bot-for-microsoft-teams-using-team-toolkit-v4-with-vs-code-3e3b</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/azure/microsoft-teams-toolkit-for-vs-code-is-now-ga-4830"&gt;In the previous post&lt;/a&gt;, I announced the Teams Toolkit for Visual Studio Code v4 made GA (generally available) status and what's new. And in this tutorial, I will walk you through how to use one of the new features to build a command bot.&lt;/p&gt;

&lt;p&gt;We are going to build a dice bot, which returns a random number between 1 and 6, when a user sends a command, "dice".&lt;/p&gt;

&lt;p&gt;So let's get started! 🎲&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Setting up
&lt;/h2&gt;

&lt;p&gt;If this is the first time using Teams Toolkit, please go to this tutorial, &lt;strong&gt;&lt;a href="https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g"&gt;Using VS Code Teams Toolkit Extension for Teams App Development&lt;/a&gt;&lt;/strong&gt; first, and follow the &lt;strong&gt;Prerequisites&lt;/strong&gt; then, &lt;strong&gt;Installing Teams Toolkit section&lt;/strong&gt;. The tutorial was written for the earlier version of Toolkit, but the initial setup process is the same.&lt;/p&gt;

&lt;p&gt;I have created a YouTube video this time, so check it out!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BSxanVdealA"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  🏗 Scaffolding a Command Bot Template
&lt;/h2&gt;

&lt;p&gt;In Teams Toolkit extension in VS Code, click &lt;strong&gt;Create a new Teams app&lt;/strong&gt; then select the &lt;strong&gt;Command bot&lt;/strong&gt; from the menu. See the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foas3exogr0wloho3j2dv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foas3exogr0wloho3j2dv.png" alt="Screenshot of Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the Teams Toolkit by choosing a language, well, let's choose &lt;strong&gt;JavaScript&lt;/strong&gt; for this tutorial, then, where in your local folder to create the project. Now give the app a name. Let's name it "RollADice".&lt;/p&gt;

&lt;p&gt;After you are done, Teams Toolkit will generate the scaffolding for you. Take a look around the code structure and familiarize yourself with the files!&lt;/p&gt;
&lt;h2&gt;
  
  
  ⌨️ Running the Template Code in Teams
&lt;/h2&gt;

&lt;p&gt;Now, let's try running the scaffolded code on Teams client and see how the bot user-experience is like.&lt;/p&gt;

&lt;p&gt;From the &lt;strong&gt;Run and Debug&lt;/strong&gt; menu, choose &lt;strong&gt;Debug (Edge)&lt;/strong&gt; (Chrome is fine, if you prefer!), and run by clicking the &lt;strong&gt;Start debugging&lt;/strong&gt; green triangle. Or alternatively, press &lt;strong&gt;F5&lt;/strong&gt; key on your keyboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w5c85266k0rckc9mda3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w5c85266k0rckc9mda3.png" alt="Screenshot of Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Teams Toolkit will do some works for you, including checking prerequisites, Azure provision and bot registration, running ngrok to tunnel your local server, etc. You will be asked to sign in to your M365 account if this is your first time. Just follow the Toolkit instructions.&lt;/p&gt;

&lt;p&gt;It will take a while, but when it is done, a browser will load Teams client, then ask you to install the bot. So, go ahead and click &lt;strong&gt;Add&lt;/strong&gt; to install your bot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghm7rn8lozfugahoqopj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghm7rn8lozfugahoqopj.png" alt="Screenshot of Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you add the bot, play around and see how it works. Notice that the command suggestions box pops up, like the screenshot below. This is a hint for the users what commands are available for the bot. Try clicking it to send the command to the bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazc9cf2eclgoo53zangs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazc9cf2eclgoo53zangs.png" alt="Screenshot of the bot running on Teams client"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🎲 Creating Roll-A-Dice Bot
&lt;/h2&gt;

&lt;p&gt;Now, let's go back to VS Code and modify the code to turn it into a dice bot. &lt;/p&gt;
&lt;h3&gt;
  
  
  🪄 Defining the Command Suggestion
&lt;/h3&gt;

&lt;p&gt;We are going to edit the suggestions content first, and this is the result of what we are going to do here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0in800sqi2vtxw3tjc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0in800sqi2vtxw3tjc5.png" alt="Teams command bot suggestion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the file, &lt;strong&gt;templates&lt;/strong&gt; &amp;gt; &lt;strong&gt;appPackage&lt;/strong&gt; &amp;gt; &lt;strong&gt;manifest.template.json&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;This is the file where the suggestions UI content is defined. Find the &lt;code&gt;commands&lt;/code&gt; in &lt;code&gt;commandLists&lt;/code&gt; in the JSON and change the title and description to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Roll a dice!"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and save the file.&lt;/p&gt;

&lt;h3&gt;
  
  
  💬 Command and Response
&lt;/h3&gt;

&lt;p&gt;Now, go to &lt;strong&gt;bot&lt;/strong&gt; &amp;gt; &lt;strong&gt;src&lt;/strong&gt; &amp;gt; &lt;strong&gt;helloWorldCommandHandler.js&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;HelloWorldCommandHandler&lt;/code&gt; class, find the line, where the &lt;code&gt;triggerPatterns&lt;/code&gt; is defined and edit the command to "dice":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;triggerPatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to worry about the case of the command. Users can type "dice", "Dice", "DICE", "DiCe", and they are all valid commands!&lt;/p&gt;

&lt;p&gt;Then, define the bot reply message. In the &lt;code&gt;handleCommandReceived&lt;/code&gt; function, let's create a message content with a generate random number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleCommandReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Generate a random number between 1 and 6&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Images of dice faces (Using creative commons images from Wikimedia)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Kismet-Ace.png/240px-Kismet-Ace.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Kismet-Deuce.png/240px-Kismet-Deuce.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Kismet-Trey.png/240px-Kismet-Trey.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Kismet-Four.png/240px-Kismet-Four.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Kismet-Five.png/240px-Kismet-Five.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Kismet-Six.png/240px-Kismet-Six.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Reply message - rendered in an Adaptive Card&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Roll a Dice 🎲&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You've got &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MessageBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachAdaptiveCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;helloWorldCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cardData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🪪 Creating Message UI with Adaptive Cards
&lt;/h3&gt;

&lt;p&gt;Here, I want to display a dice image along with the result in a reply message nicely, so we are going to use &lt;a href="https://adaptivecards.io/?WT.mc_id=m365-79637-timura" rel="noopener noreferrer"&gt;Adaptive Cards&lt;/a&gt; to customize the message UI layout. &lt;/p&gt;

&lt;p&gt;The layout is defined in JSON in the file at &lt;strong&gt;bot&lt;/strong&gt; &amp;gt; &lt;strong&gt;src&lt;/strong&gt; &amp;gt; &lt;strong&gt;adaptiveCards&lt;/strong&gt; &amp;gt; &lt;strong&gt;helloworldCommand.json&lt;/strong&gt;. But let's hold on to it and we'll come back to the file later because we are going to use a visual tool to create the JSON first.&lt;/p&gt;

&lt;p&gt;In a browser, go to &lt;strong&gt;Adaptive Cards Editor&lt;/strong&gt; tool section in Developer Portal at &lt;a href="https://dev.teams.microsoft.com/cards?WT.mc_id=m365-79637-timura" rel="noopener noreferrer"&gt;dev.teams.microsoft.com/cards&lt;/a&gt;, create a new card by clicking &lt;strong&gt;Create new card&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's use the &lt;strong&gt;Thumbnail card&lt;/strong&gt; template as a starting point. In the preview pane, delete the buttons and text in the template and leave only a thumbnail, title, and subtitle, to create a simple UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7a0ld9laouijznam8hk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7a0ld9laouijznam8hk.png" alt="Screenshot of Adaptive Cards Editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The edit I made for the tutorial are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove buttons and text from the template&lt;/li&gt;
&lt;li&gt;Set the thumbnail layout property for size to "medium"&lt;/li&gt;
&lt;li&gt;Double-click the title and change to a variable, "${title}"&lt;/li&gt;
&lt;li&gt;Set the title style property for weight to "bolder"&lt;/li&gt;
&lt;li&gt;Change the subtitle to "${body}"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But feel free to customize in the way you want!&lt;/p&gt;

&lt;p&gt;Now, copy the generated JSON into the &lt;strong&gt;helloworldCommand.json&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the YouTube tutorial, you can follow the instruction at &lt;a href="https://www.youtube.com/watch?v=BSxanVdealA&amp;amp;t=286s?WT.mc_id=m365-79637-timura" rel="noopener noreferrer"&gt;4:46&lt;/a&gt; and watch me how to use the tool. In the video, I copy &amp;amp; paste the JSON first then modify some content manually, instead of editing all properties in the visual tool. You can do in either way.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Running the Bot
&lt;/h3&gt;

&lt;p&gt;Let's run the code in Teams client again, using the "F5" tool and see how it works. Once added the bot, try sending the "dice" command. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr8rsz8van8zb68qm6kx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr8rsz8van8zb68qm6kx.png" alt="Screenshot of a bot running on Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope your bot works as it should 🎲&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Hacking it More
&lt;/h2&gt;

&lt;p&gt;Now, you know the basics of command bots for Teams, so I suggest you to tweak the bot further to make it more interesting.&lt;/p&gt;

&lt;p&gt;The bot we just created is a 6-faced dice and only replies you with a number between 1 and 6. But it would be more interesting if each user can decide the type of dice, such as, 12 sided dodecahedron, 20 sided icosahedron, chiliagon with 1000 sides, or any n-sided theroritical dice.&lt;/p&gt;

&lt;p&gt;So we can make the bot to take a parameter along with the command, such as &lt;code&gt;dice 12&lt;/code&gt; so that the dice bot can return a number between 1 and 12. Or between 1 and 1000 for &lt;code&gt;dice 1000&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;You can tweak the code to read a parameter like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MessageBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachHeroCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Invalid number: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Roll a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-sided dice 🎲`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You've got &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84ayucdz5x9okys43ah8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84ayucdz5x9okys43ah8.png" alt="Screenshot of a bot running on Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't forget to modify the command suggestion UI content too. I totally encourage you to modify the code more and add features to create your own dice bot!&lt;/p&gt;

&lt;p&gt;Or Use your imagination to build something else, like weather bot, cryptocurrency bot, dad joke bot... The ideas are endless. &lt;/p&gt;

&lt;p&gt;If you build some interesting bots, please let me know! Mahalo, and see you in the next blog post 🤙&lt;/p&gt;

&lt;h2&gt;
  
  
  📖 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📺 YouTube: &lt;a href="https://youtu.be/BSxanVdealA" rel="noopener noreferrer"&gt;Roll A Dice! - Building a Command Bot for Microsoft Teams Using Team Toolkit v4 with VS Code 🎲&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📄 Docs: &lt;a href="https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals?WT.mc_id=m365-79637-timura" rel="noopener noreferrer"&gt;Teams Toolkit Overview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📄 Docs: &lt;a href="https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/teams-developer-portal?WT.mc_id=m365-79637-timura" rel="noopener noreferrer"&gt;Developer Portal for Teams - Overview&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>msteams</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>bot</category>
    </item>
    <item>
      <title>Microsoft Teams Toolkit for VS Code is now GA 🎉</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Tue, 24 May 2022 18:04:35 +0000</pubDate>
      <link>https://dev.to/azure/microsoft-teams-toolkit-for-vs-code-is-now-ga-4830</link>
      <guid>https://dev.to/azure/microsoft-teams-toolkit-for-vs-code-is-now-ga-4830</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/azure/developing-enterprise-ready-microsoft-teams-apps-with-teams-toolkit-v30-o87"&gt;Previously&lt;/a&gt;, I introduced Teams Toolkit Preview in a series of blog posts. And I am happy to announce that &lt;a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.ms-teams-vscode-extension" rel="noopener noreferrer"&gt;Teams Toolkit for Visual Studio Code&lt;/a&gt; and the Teams Toolkit CLI are &lt;em&gt;generally available&lt;/em&gt; as of today! And for everyone building .NET web apps, Teams Toolkit for Visual Studio is available now in preview. I hope you caught the announcement at Microsoft Build 2022 too.&lt;/p&gt;

&lt;p&gt;There have been a lot of updates and improvement since the preview versions, however, in this post, I'd like to highlight some of the key new features with Teams Toolkit for VS Code that probably excite you the most!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ff193v85f0butylm0ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ff193v85f0butylm0ix.png" alt="Doodles illustrating the summary of Teams Toolkit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎞 Introducing Scenario-based Teams Apps
&lt;/h2&gt;

&lt;p&gt;Before this release, Teams Toolkit Preview has provided app template code based on the Teams capabilities, such as &lt;a href="https://docs.microsoft.com/microsoftteams/platform/tabs/what-are-tabs?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;Tabs&lt;/a&gt;, &lt;a href="https://docs.microsoft.com/microsoftteams/platform/bots/what-are-bots?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;Bots&lt;/a&gt;, and &lt;a href="https://docs.microsoft.com/microsoftteams/platform/messaging-extensions/what-are-messaging-extensions?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;Messaging Extensions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, in the reality, we design products based on the &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/overview-story?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;real-life scenarios&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview%2Fdeveloper-scenario.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview%2Fdeveloper-scenario.png" alt="User story illustrated - a travel agent wants to build an app that sends weather forecast notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, with this GA release, we have added the scenario-based Teams app template, along with the existing basic capabilities templates.&lt;/p&gt;

&lt;p&gt;Here are the newly added features—&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Bot Notifications
&lt;/h3&gt;

&lt;p&gt;Sending bot notification can be a common scenario for a chat bot applications and for Teams app too. However, the development process for Teams apps has been cumbersome... Well, we made the process simpler as Toolkit now can help you create the notification feature for your app by tweaking the generated code!&lt;/p&gt;

&lt;p&gt;When you are first setting up a new app in Teams Toolkit, click &lt;strong&gt;Notification bot&lt;/strong&gt; under Scenario-based Teams app. to let Toolkit generate the scaffolding to create a bot that sends notifications. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zmroxq1rcw72kuvwfpl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zmroxq1rcw72kuvwfpl.png" alt="Screenshot of Teams Toolkit on VS Code showing the app creation with bot notification menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can specify the event for that message—a trigger or a timer. If you want your bot to send Teams periodical reminder of something, choose the Timer Trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj69miy1ze3f2yju4vpa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj69miy1ze3f2yju4vpa.png" alt="Screenshot of Teams Toolkit on VS Code showing the app creation with bot notification trigger options"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are using JavaScript, take a look at the file, &lt;code&gt;source/adaptiveCards/notification-default.json&lt;/code&gt; and see where specifies the message structure in JSON. You can keep the message just with some simple text, or with a list, table, buttons, etc.&lt;/p&gt;

&lt;p&gt;You can also live-preview how the JSON is displayed as the Adaptive Card too. Just click where it says &lt;strong&gt;Preview and Debug Adaptive Cards&lt;/strong&gt; to preview, or get the VS Code extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkowaeke5j3kvnk9y27pe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkowaeke5j3kvnk9y27pe.png" alt="Screenshot of Teams Toolkit on VS Code showing Adaptive card viewer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in &lt;code&gt;src/timerTrigger.js&lt;/code&gt; (for Timer-based notifications), you can see how the message to be sent is applied to the Adaptive Card. Try changing the strings and see how it works on Teams client!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;installations&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendAdaptiveCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;AdaptiveCards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationTemplate&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Aloha! This is your daily reminder.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Contoso Bot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`This is a sample time-triggered notification (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timeStamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;).`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;notificationUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.adaptivecards.io/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you run the bot with the F5 debugger, the bot sends you a notification in your scheduled time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbbqb6pap9hi39anewpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbbqb6pap9hi39anewpu.png" alt="Screenshot of a bot sending a message on Teams client"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are more you can do with bots—&lt;/p&gt;

&lt;h3&gt;
  
  
  💬 Command Bot
&lt;/h3&gt;

&lt;p&gt;Another common scenario would be a bot that respond to a command. You might think about some conversational bot but for most cases, all you need is a simple bot that answers your commands, like what you may have used "slash commands" in some services. &lt;/p&gt;

&lt;p&gt;Now with the Toolkit, you can start creating a command bot easier than ever. &lt;/p&gt;

&lt;p&gt;After clicking &lt;strong&gt;Create a new Teams&lt;/strong&gt; app in Teams Toolkit, select the &lt;strong&gt;Command bot&lt;/strong&gt; from the menu and proceed the rest.&lt;/p&gt;

&lt;p&gt;Once the template code is generated, see the &lt;code&gt;commandHandler&lt;/code&gt; function. For example, if you chose JavaScript, the file, &lt;code&gt;bot/src/helloWorldCommandHandler.js&lt;/code&gt; you see the trigger word and response message.&lt;/p&gt;

&lt;p&gt;You can alter the handler (or create a new handler) to create your command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorldCommandHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;triggerPatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hi kitty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleCommandReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// render your adaptive card for reply message&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MeowBot 🐱 says&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Meow meow meow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://placekitten.com/500/400&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;imageAlt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MessageBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachAdaptiveCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;helloWorldCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cardData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And define the response message UI with the Adaptive Cards previewer in &lt;code&gt;bot/src/adaptiveCards/helloworldCommand.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, when a user send a "Hi kitty" message to the bot, the bot will respond.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs357fd8ys0fn4iqo3cf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs357fd8ys0fn4iqo3cf7.png" alt="Screenshot of a bot responding to the command from a user on Teams client"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📬 Expand Your Apps to Outlook and Office
&lt;/h2&gt;

&lt;p&gt;Another exciting news is that now your Teams apps can run on Outlook and Office! &lt;/p&gt;

&lt;p&gt;When you create a new app, the previous version of Toolkit only allowed you to choose one of the capabilities, however, with the new Toolkit, now you have more choices. &lt;/p&gt;

&lt;p&gt;To create an app that runs on other M365 products, like Outlook and Office, choose one from the &lt;strong&gt;Extended Teams app across Microsoft 365&lt;/strong&gt;, which will generate a scaffolding code with helpful code template and samples, either in JavaScript or TypeScript (which, you can choose one!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup9b0td6nql6kpmpo0n3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup9b0td6nql6kpmpo0n3.png" alt="Screenshot of Teams Toolkit on VS Code showing the create menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "F5" debug feature is your friend when you are testing out your code in VS Code, and now the debug profile in Teams Toolkit includes Outlook and Office, where you can simply select one and see your app running!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy0jp4aeqq4nxwcrckv0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy0jp4aeqq4nxwcrckv0.png" alt="Screenshot of Teams Toolkit on VS Code showing the debug menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe386gtaee8uqvy0vz6rc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe386gtaee8uqvy0vz6rc.png" alt="Screenshot of Teams and Outlook where the app is running"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📢 More Updates for Teams Development
&lt;/h2&gt;

&lt;p&gt;There are more updates with Teams and M365 app developments.&lt;/p&gt;

&lt;h3&gt;
  
  
  📜 Teams SDK v2 &amp;amp; Updated Manifest
&lt;/h3&gt;

&lt;p&gt;Teams client SDK has been around for you to create tabs and task modules, and come with functionalities like tab configurations and theme detection, as well as authentication. Now it is upgraded to v2, and the latest version comes with functionalities to extend Teams app to run in Outlook and Office. &lt;/p&gt;

&lt;p&gt;The new Teams Toolkit utility also allows you to upgrade your existing apps that uses Teams-js SDK v1 to use the SDK v2, which updates imports &amp;amp; API calls. &lt;/p&gt;

&lt;p&gt;Toolkit also revises a Teams manifest to the latest schema to support Office and Outlook.&lt;/p&gt;

&lt;h3&gt;
  
  
  🖼 Fluent UI Component Library for Tabs App
&lt;/h3&gt;

&lt;p&gt;When creating a tab app (which is a web embed in Teams), you would want the UI for your app to look and feel like Teams. &lt;br&gt;
The &lt;strong&gt;Teams UI Component Library&lt;/strong&gt; is here to help with that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OfficeDev/microsoft-teams-ui-component-library" rel="noopener noreferrer"&gt;Teams UI Component Library&lt;/a&gt; is a UI library built on top of &lt;strong&gt;Fluent UI React&lt;/strong&gt;. &lt;br&gt;
Fluent is Microsoft’s design system that provides you with a set of UI libraries for all M365. &lt;/p&gt;

&lt;p&gt;And the base components library, &lt;a href="https://github.com/microsoft/fluentui" rel="noopener noreferrer"&gt;Fluent UI React&lt;/a&gt; is now upgraded to v9, which supports design tokens and has major performance improvements 🎉&lt;/p&gt;




&lt;p&gt;I hope you found the article makes you get started with your Teams app development with Teams Toolkit, especially if you are new to Teams app development!&lt;/p&gt;

&lt;p&gt;Please don't hesitate to drop your comments and feedback here.&lt;/p&gt;

&lt;p&gt;See you again at the next post 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/teams-toolkit-fundamentals?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;Teams Toolkit documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview?WT.mc_id=m365-66412-timura" rel="noopener noreferrer"&gt;Get started with Microsoft Teams platform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📢 Shoutout
&lt;/h3&gt;

&lt;p&gt;A big hurrah to Teams Toolkit Engineering team, and thank you, Yu Zhang, Zhidi Shang, John Miller, Zhenya Savchenko, and Pierce Boggan, for helping me writing this article ❤️&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>vscode</category>
      <category>msteams</category>
    </item>
    <item>
      <title>Debugging Teams App Locally with Teams Toolkit</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Fri, 04 Mar 2022 06:20:43 +0000</pubDate>
      <link>https://dev.to/azure/debugging-teams-app-locally-with-teams-toolkit-2b67</link>
      <guid>https://dev.to/azure/debugging-teams-app-locally-with-teams-toolkit-2b67</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/azure/developing-enterprise-ready-microsoft-teams-apps-with-teams-toolkit-v30-o87"&gt;In the previous post&lt;/a&gt;, I introduced some of the new features in Teams Toolkit v3 to empower enterprise Teams developers.&lt;/p&gt;

&lt;p&gt;In this article, I will show you the improved local debug experience in Toolkit and new features introduced in version 3.4.&lt;/p&gt;

&lt;p&gt;First of all, you need to install Teams Toolkit extension in Visual Studio Code, or update it to the latest version if you already have it. And if this is the first time interacting with Teams Toolkit, I recommend to go through the step-by-step tutorial, &lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview/?WT.mc_id=m365-58952-timura" rel="noopener noreferrer"&gt;&lt;strong&gt;Get started&lt;/strong&gt;&lt;/a&gt; with JavaScript on Microsoft Teams developer platform documentation first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4yakatrmrxmij5xvndt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4yakatrmrxmij5xvndt.png" alt="Doodle summarizing this article"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⌨ Debugging with "F5"
&lt;/h2&gt;

&lt;p&gt;Debugging, casually referred to as &lt;em&gt;F5&lt;/em&gt; (function key) among developers, is one of the key features of &lt;a href="https://code.visualstudio.com/docs/editor/debugging/?WT.mc_id=m365-58952-timura" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;, and this built-in debugger helps accelerate your edit, compile, and debug loop.&lt;/p&gt;

&lt;p&gt;Teams Toolkit uses the VS Code feature to let you run your app in Teams client and debug it during the development.&lt;/p&gt;

&lt;p&gt;To enable local debugging in Teams Toolkit, first, &lt;em&gt;make sure you are logged in with your M365 account&lt;/em&gt; under the &lt;strong&gt;Accounts&lt;/strong&gt; section in Toolkit. Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On VS Code, go to the &lt;strong&gt;Run and Debug&lt;/strong&gt; view in the Activity Bar &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select either &lt;strong&gt;Debug (Chrome)&lt;/strong&gt; or &lt;strong&gt;Debug (Edge)&lt;/strong&gt; from the dropdown menu on the debug button and click the ▶️ (Start) icon&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv0y2e8iqu5etezsv7ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv0y2e8iqu5etezsv7ps.png" alt="Screenshot of VS Code showing how to manually enable the F5 Debug feature"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, you can just press &lt;strong&gt;F5&lt;/strong&gt; function key on your keyboard.&lt;/p&gt;

&lt;p&gt;Toolkit will launch Teams client in a new Chrome or Edge browser, where you can add your app. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ If this is the first time with Teams Toolkit, you will be prompted to confirm to add an SSL certificate. Please agree to continue.&lt;br&gt;
Since Teams requires https Tab hosting endpoint, a localhost development certificate will be automatically generated and installed to your system after your confirmation. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📍 Using Breakpoints
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/editor/debugging#_breakpoints" rel="noopener noreferrer"&gt;Breakpoints in VS Code&lt;/a&gt; is available in Toolkit too to debug your code for tab, bot, message extension, and Azure Functions. You can toggle the breakpoints while your app is running on Teams client on browser.&lt;/p&gt;

&lt;p&gt;Click the left margin next to the line you wish to stop so the breakpoint will appear as a red dot 🔴. Then run the code (F5). &lt;/p&gt;

&lt;p&gt;Your code will pause before the marked execution. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghazg9cg92dixhrm4nqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghazg9cg92dixhrm4nqy.png" alt="Screenshot of VS Code showing debugging with breakpoints"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once a debug session starts, the Debug toolbar will appear on the top of the editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fferur793j1hw6yfxelks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fferur793j1hw6yfxelks.png" alt="Screenshot of VS Code showing debug toolbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continue / Pause &lt;code&gt;F5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Over &lt;code&gt;F10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Into &lt;code&gt;F11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Out &lt;code&gt;⇧F11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Restart &lt;code&gt;⇧⌘F5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stop &lt;code&gt;⇧F5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Multi-target debug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last action in a dropdown menu is for selecting a &lt;a href="https://code.visualstudio.com/docs/editor/debugging#_multitarget-debugging/?WT.mc_id=m365-58952-timura" rel="noopener noreferrer"&gt;multi-target debugging&lt;/a&gt;. In Teams Toolkit, selecting "Attach to Frontend" (for tabs) or "Attach to Bot" (for bots and messaging extension) will trigger a Node.js debugger, as well as Edge or Chrome debugger to launch a new browser instance and open a web page to load Teams client. "Attach to Backend" will start a Node.js debugger to attach to the Azure functions source code.&lt;/p&gt;

&lt;p&gt;Also note that &lt;strong&gt;Hot reload&lt;/strong&gt; is enabled in Toolkit so you can just update your code and save the changes, then your app will automatically reload and re-attach the debugger.&lt;/p&gt;

&lt;p&gt;To end the debugging, disconnect in the floating toolbar. Once the session is terminated, it is safe to run again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidl99lfkerrrd3vzvv3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidl99lfkerrrd3vzvv3k.png" alt="Screenshot of VS Code showing the disconnect button in debug toolbar"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🐞 What's New with Local Debug Experience in Toolkit v3.4?
&lt;/h2&gt;

&lt;p&gt;There are a few new features that have been added in the latest Toolkit to improve your local debugging experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Prerequisite Checker
&lt;/h3&gt;

&lt;p&gt;In case you wonder, when you press the F5 key, the Teams Toolkit does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Register your app with Azure Active Directory&lt;/li&gt;
&lt;li&gt;Start app services for both backend and frontend&lt;/li&gt;
&lt;li&gt;Start Microsoft Teams in a web browser with a command to instruct Teams to sideload the app from &lt;code&gt;localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create an app manifest and register the app in &lt;a href="https://dev.teams.microsoft.com/home" rel="noopener noreferrer"&gt;Teams Developer Portal&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These processes require specific versions of Node.js, packages, various tools, also M365 credentials.&lt;/p&gt;

&lt;p&gt;Now in Toolkit v3.4, it checks all the requirements and lists up and displays in Output channel: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85y7jx3pw2v6z6b6vx8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85y7jx3pw2v6z6b6vx8i.png" alt="Screenshot of VS Code showing the prerequisites checker in Output console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives you more transparency and clear ideas about what is going on and easier to figure out when something goes wrong. &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Customizing Local Debug Settings
&lt;/h3&gt;

&lt;p&gt;Another new feature is that now Toolkit allows you to customize the debug settings. This gives you control over your debugging experience.&lt;/p&gt;

&lt;h4&gt;
  
  
  Skipping Prerequisites
&lt;/h4&gt;

&lt;p&gt;You can skip some of the prerequisites in VS Code Settings: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Settings&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;Extensions&lt;/strong&gt; in the list and expand it&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;Teams Toolkit (Preview)&lt;/strong&gt; and click &lt;strong&gt;Prerequisite Check&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn26b266eafjo706ho4om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn26b266eafjo706ho4om.png" alt="Screenshot of VS Code Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have the checkboxes so you can uncheck the items you would like to skip.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Your Own Bot Endpoint
&lt;/h4&gt;

&lt;p&gt;Teams Toolkit uses the 3rd party tool called, &lt;strong&gt;ngrok&lt;/strong&gt; to tunnels your localhost to the internet to run bots. If you wish to use your own bot endpoint,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;At Prerequisites Check in VS Code Settings, &lt;strong&gt;uncheck&lt;/strong&gt; "Ensure Ngrok is installed and started. (ngrok)"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;botDomain&lt;/code&gt; and &lt;code&gt;botEndpoint&lt;/code&gt; configuration in &lt;code&gt;.fx/configs/localSettings.json&lt;/code&gt; to your own domain and endpoint&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Using Your Own Development Certificate
&lt;/h4&gt;

&lt;p&gt;Similarly, you can use your own development certificate, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;At Prerequisites Check in VS Code Settings, &lt;strong&gt;uncheck&lt;/strong&gt; "Ensure development certificate is trusted. (devCert)". &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;sslCertFile&lt;/code&gt; and &lt;code&gt;sslKeyFile&lt;/code&gt; configuration in &lt;code&gt;.fx/configs/localSettings.json&lt;/code&gt; to your own certificate file path and key file path.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can learn more about the certificate in &lt;a href="https://github.com/OfficeDev/TeamsFx/blob/dev/docs/fx-core/localdebug-help.md#what-to-do-if-i-do-not-want-to-install-the-development-certificate" rel="noopener noreferrer"&gt;TeamsFx documentation&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Manual Customizations
&lt;/h3&gt;

&lt;p&gt;You can also customize your local debug settings manually with editing configuration files.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Your Own Start Scripts
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;For tab:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update &lt;code&gt;dev:teamsfx&lt;/code&gt; script in &lt;code&gt;tabs/package.json&lt;/code&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;For bot or messaging extension:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update &lt;code&gt;dev:teamsfx&lt;/code&gt; script in &lt;code&gt;bot/package.json&lt;/code&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;For Azure functions:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update &lt;code&gt;dev:teamsfx&lt;/code&gt; script in &lt;code&gt;api/package.json&lt;/code&gt;. In addition for TypeScript, update &lt;code&gt;watch:teamsfx&lt;/code&gt; script.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ The ports required by tab app, bot app, messaging extension app and Azure functions are not supported to be customized currently&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Adding Environmental Variables
&lt;/h4&gt;

&lt;p&gt;You can add environment variables to &lt;code&gt;.env.teamsfx.local&lt;/code&gt; file for tab, bot, messaging extension and Azure functions. &lt;/p&gt;

&lt;p&gt;Teams Toolkit will load the environment variables you added to start services during local debug. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ The environment variables are not supported to hot reload. You need to start a new local debug after adding new environment variables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Debugging Partial Component
&lt;/h4&gt;

&lt;p&gt;Teams Toolkit utilizes VS Code multi-target debugging to debug tab, bot, messaging extension and Azure functions at the same time. &lt;/p&gt;

&lt;p&gt;You can updates &lt;code&gt;.vscode/launch.json&lt;/code&gt; and &lt;code&gt;.vscode/tasks.json&lt;/code&gt; to debug partial component. Let's say, you want to debug tab only in an app with tab and bot capabilities with Azure functions project, you can take the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comment out these lines in &lt;code&gt;.vscode/launch.json&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Debug (Edge)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"Attach to Frontend (Edge)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Attach to Bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Attach to Backend"&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Comment out these lines in &lt;code&gt;.vscode/tasks.json&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Start All"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"Start Frontend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Start Backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Start Bot"&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope you found the article helpful for debugging your Teams apps and the new features give you more confidence debugging your Teams app development! &lt;/p&gt;

&lt;p&gt;Please don't hesitate to drop your comments and feedback here. &lt;/p&gt;

&lt;p&gt;See you until the next post 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/teams-toolkit-fundamentals?WT.mc_id=m365-58952-timura" rel="noopener noreferrer"&gt;Teams Toolkit documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview/?WT.mc_id=m365-58952-timura" rel="noopener noreferrer"&gt;Get started with Microsoft Teams platform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📢 Shoutout
&lt;/h3&gt;

&lt;p&gt;Teams Toolkit Engineering team, especially Kuojian Lu and Yu Zhang ❤️&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vscode</category>
      <category>msteams</category>
      <category>azure</category>
    </item>
    <item>
      <title>Developing Enterprise-Ready Microsoft Teams Apps with Teams Toolkit v3.0</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Wed, 01 Dec 2021 21:54:04 +0000</pubDate>
      <link>https://dev.to/azure/developing-enterprise-ready-microsoft-teams-apps-with-teams-toolkit-v30-o87</link>
      <guid>https://dev.to/azure/developing-enterprise-ready-microsoft-teams-apps-with-teams-toolkit-v30-o87</guid>
      <description>&lt;p&gt;In the earlier posts, &lt;a href="https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g"&gt;I introduced Teams Toolkit v2 Developer Preview extension for Visual Studio Code&lt;/a&gt; that generates scaffolding for you to help you get started with Microsoft Teams apps, also, &lt;a href="https://dev.to/azure/fetching-teams-user-info-from-microsoft-graph-with-teamsfx-sdk-301c"&gt;introduced TeamsFx&lt;/a&gt;, the core library that lets you handle things like authorization and making Graph API calls.&lt;/p&gt;

&lt;p&gt;Since then, the tool has evolved with more powerful features and better user-experience. Thereby, in this article, I would like to introduce new features in the Toolkit v3.0, especially to empower enterprise Teams developers 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs9xnj4dcvtrflgrlj17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs9xnj4dcvtrflgrlj17.png" alt="Doodle that describes Microsoft Teams Toolkit v3 features"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Intro—What are Teams Toolkit &amp;amp; TeamsFx CLI?
&lt;/h2&gt;

&lt;p&gt;Teams Toolkit is a collection of development tools that helps you to create and deploy Microsoft Teams apps with integrated identity, access to cloud storage, data from Microsoft Graph, and other services in Azure and Microsoft 365.&lt;/p&gt;

&lt;p&gt;There are a visual interface tool and a command line interface—With Teams Toolkit extension for Visual Studio, you can take advantage of the familiar VS Code visual interface for Teams app development. Teams Toolkit comes with a Command-line tool, called &lt;em&gt;TeamsFx CLI&lt;/em&gt;, which lets you run tasks with keyboard-centric experience, as well as enabling CI/CD scenarios.&lt;/p&gt;

&lt;p&gt;Now, let's take a look at what the new features these tools offer! And if you are looking to learn how to get started with Teams Toolkit and the requirement to start developing Teams apps in general, I'd recommend reading &lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview/?WT.mc_id=m365-51046-timura" rel="noopener noreferrer"&gt;Get started documentation&lt;/a&gt; on Microsoft Teams developer platform docs first.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☁️ Multi-Env Management
&lt;/h2&gt;

&lt;p&gt;You typically start developing in your local environment, but sooner or later, you will need to manage multiple environments as you go. Besides your local env, you probably end up having multiple environments, such as, &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;qa&lt;/code&gt;, &lt;code&gt;stage&lt;/code&gt;, and the production environment, &lt;code&gt;prod&lt;/code&gt; to deploy.&lt;/p&gt;

&lt;p&gt;Teams Toolkit provides a simple way for you to create and manage multiple environments. When you created a new project with Teams Toolkit, it generates &lt;code&gt;local&lt;/code&gt; for your local machine configurations, and &lt;code&gt;dev&lt;/code&gt;, to represent a remote environment configurations by default.&lt;/p&gt;

&lt;p&gt;Now, with this new Toolkit, you can enable more remote environment 🎉&lt;/p&gt;

&lt;p&gt;To add an extra environment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open a project in Teams Toolkit, and find &lt;strong&gt;Environment&lt;/strong&gt; on the left pane&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Create new environment&lt;/strong&gt; button (a little "Plus sign" button)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5nprplvvau4zvkv3eys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5nprplvvau4zvkv3eys.png" alt="MS Teams Toolkit v3 - Multi-env setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.Give a name to the new environment and press Enter key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybv1r3u8059zmaqh46z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybv1r3u8059zmaqh46z2.png" alt="MS Teams Toolkit v3 - Multi-env setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfcdqf56nyxnx1rd1bza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfcdqf56nyxnx1rd1bza.png" alt="MS Teams Toolkit v3 - Multi-env setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add more environments, select an existing environment to add a new one. Every time you create an extra environment, the configuration file (&lt;code&gt;config.&amp;lt;your_new_env&amp;gt;.json&lt;/code&gt; and &lt;code&gt;azure.parameters.&amp;lt;your_new_env&amp;gt;.json&lt;/code&gt;) will be copied from an existing one.&lt;/p&gt;

&lt;p&gt;For more info, please read &lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/teamsfx-multi-env?WT.mc_id=m365-51046-timura" rel="noopener noreferrer"&gt;Manage multiple environments in Teams Toolkit.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 Collaboration Among Multiple Developers
&lt;/h2&gt;

&lt;p&gt;Have you wished it was easier to collaborate on a Teams app project with your coworkers? Well, I have good news! This much-anticipated feature to manage multiple environments was introduced in the latest version of Teams Toolkit, and it supports project collaborations among multiple developers.&lt;/p&gt;

&lt;p&gt;Previously, you needed to manually handle the permissions for Teams and Azure AD. But from now on, the Toolkit handles this for you.&lt;/p&gt;

&lt;p&gt;To add a collaborator:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, make sure you have logged in to both M365 and Azure accounts from the menu under &lt;strong&gt;Account&lt;/strong&gt; in Teams Toolkit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b8tb3ffv9r735b5mkk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b8tb3ffv9r735b5mkk0.png" alt="MS Teams Toolkit v3 - Add collaborator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.Under &lt;strong&gt;Development&lt;/strong&gt; , click &lt;strong&gt;Provision in the cloud&lt;/strong&gt;&lt;br&gt;
3.Then choose an environment (if you have multiple working environments). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbmuexjrlv9xg9rj9ued.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbmuexjrlv9xg9rj9ued.png" alt="MS Teams Toolkit v3 - Add collaborator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may see some popup notifications. Follow the instructions. This will create necessary cloud resources.&lt;/p&gt;

&lt;p&gt;4.Once the provision process is completed, now you see the Collaborators list is available under &lt;strong&gt;Environment&lt;/strong&gt;. Click the little &lt;strong&gt;Add M365 Teams App (with AAD App) Owners&lt;/strong&gt; icon &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mduo111qx9iculjnwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mduo111qx9iculjnwf.png" alt="MS Teams Toolkit v3 - Add collaborator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5.Then enter an email address of the person who you want to invite&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkb2mxxl7cgzi3gq2kur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkb2mxxl7cgzi3gq2kur.png" alt="MS Teams Toolkit v3 - Add collaborator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6.To view collaborators in the environment, select &lt;strong&gt;List M365 Teams App (with AAD App) Owners&lt;/strong&gt; button, then collaborators will be listed in the output channel&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvj20hwmw378z1e67rqz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvj20hwmw378z1e67rqz9.png" alt="MS Teams Toolkit v3 - Add collaborator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the collaborator joins, they can develop, provision and deploy the project. You can push the project to GitHub, so that your collaborators can clone the repository and work on the project remotely by signing in on their own M365 and Azure account credentials!&lt;/p&gt;
&lt;h2&gt;
  
  
  💪 Provision Azure Resources Using ARM and Bicep
&lt;/h2&gt;

&lt;p&gt;One of the last major upgrades of Teams Toolkit (v2) was the features that let you provision Azure resources using infrastructure-as-a-code approach and deploy your apps to Azure.&lt;/p&gt;

&lt;p&gt;Now with this new Teams Toolkit v3, you can declaratively provision to author ARM (Azure Resource Manager) template, which is a set of Bicep files that defines the infrastructure and configuration for your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview" rel="noopener noreferrer"&gt;Bicep&lt;/a&gt; is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. The advantage of using Bicep instead of JSON is that Bicep is verbose and uses simpler syntax to develop your ARM templates.&lt;/p&gt;

&lt;p&gt;To provision with ARM, you can customize Azure resources by changing these two sets of files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure parameters&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└ 📁 .fx/configs
  ├ 📄 `azure.parameters.{your_env_name}.json`
  ├ 📄 `azure.parameters.{your_env2_name}.json`
  ├ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ARM Templates (Bicep files)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└ 📁 templates/azure
  ├ 📄 main.bicep
  ├ 📄 provision.bicep
  ├ 📄 config.bicep
└ 📁 provision
  ├ 📄 {each_Azure_resource}.bicep
  ├ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are predefined parameters and templates. To learn what exactly you can customize and how, please read &lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/provision?WT.mc_id=m365-51046-timura#customize-resource-provision" rel="noopener noreferrer"&gt;Customize resource provision&lt;/a&gt; section in the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🥽 CI/ CD Support
&lt;/h2&gt;

&lt;p&gt;In your real-life development process, your team is highly likely to rely on a CI/CD platform to automate your builds, testing, and deployment.&lt;/p&gt;

&lt;p&gt;Now with Toolkit v3, you can enable CI/CD workflows to automate Teams app development process for multiple environments scenario.&lt;/p&gt;

&lt;p&gt;The Toolkit bundles with &lt;strong&gt;TeamsFx CLI&lt;/strong&gt; that comes with various useful commands for your Teams app development, including the integration for the automated CI/CD workflows.&lt;/p&gt;

&lt;p&gt;We prepared sample configuration files, including GitHub, Jenkins, Azure DevOps, and other platforms by scripts (&lt;a href="https://github.com/OfficeDev/TeamsFx/blob/main/docs/cicd_insider/README.md" rel="noopener noreferrer"&gt;Grab templates of your choice!)&lt;/a&gt;, as well as GitHub Actions template, which I will show you how—&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up GitHub Actions
&lt;/h3&gt;

&lt;p&gt;For example, if you would like to set up CI/CD flow with GitHub Actions with TeamsFx from the web interface:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On your project repo on GitHub.com, click &lt;strong&gt;Actions&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;set up a workflow yourself&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Copy the &lt;a href="https://github.com/OfficeDev/TeamsFx/blob/main/docs/cicd_insider/github-ci-template.yml" rel="noopener noreferrer"&gt;sample file for Continuous Integrations (CI)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Paste it in the editor&lt;/li&gt;
&lt;li&gt;Customize the workflow to fit your scenarios&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start commit&lt;/strong&gt; button to commit the file&lt;/li&gt;
&lt;li&gt;Repeat the process with the &lt;a href="https://github.com/OfficeDev/TeamsFx/blob/main/docs/cicd_insider/github-cd-template.yml" rel="noopener noreferrer"&gt;sample file for Continuous Deployment (CD)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fill out your M365 and Azure credentials in the CD config file, under the &lt;code&gt;env&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;Commit the file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See how to set up GitHub Actions in this GIF:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dw876dex50v200097ib.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dw876dex50v200097ib.gif" alt="Showing how to create a GitHub Actions with the CI template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These files are now stored under &lt;strong&gt;.github/workflows.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you run into a problem with your M365 account permission, please disable the multi-factor authentication from &lt;a href="https://admin.microsoft.com/" rel="noopener noreferrer"&gt;Microsoft 365 admin center.&lt;/a&gt; You should be able to change the setting at &lt;strong&gt;Users&lt;/strong&gt; &amp;gt; &lt;strong&gt;Active users&lt;/strong&gt; &amp;gt; &lt;strong&gt;Multi-factor authentication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Also, for Azure account, the account's security defaults should be turned off at &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Azure Portal,&lt;/a&gt; at &lt;strong&gt;Azure Active Directory&lt;/strong&gt; &amp;gt;  &lt;strong&gt;Properties &amp;gt; Manage security defaults&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up CI/CD Pipelines with Something Else
&lt;/h3&gt;

&lt;p&gt;If you would like to set up your workflow with other platforms, such as Azure DevOps and Jenkins, please refer to the docs at &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/toolkit/use-cicd-template" rel="noopener noreferrer"&gt;CI or CD support for Teams application developers&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;I hope these new features give more confidence to your Teams app development workflow and we are looking forward to seeing your amazing apps on production! And please don't hesitate to drop your comments and feedback here.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/toolkit/teams-toolkit-fundamentals?WT.mc_id=m365-51046-timura" rel="noopener noreferrer"&gt;Teams Toolkit documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/get-started/get-started-overview/?WT.mc_id=m365-51046-timura" rel="noopener noreferrer"&gt;Get started with Microsoft Teams platform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vscode</category>
      <category>msteams</category>
      <category>tutorial</category>
      <category>azure</category>
    </item>
    <item>
      <title>Fetching Teams User Info from Microsoft Graph with TeamsFx SDK</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Thu, 29 Jul 2021 21:26:21 +0000</pubDate>
      <link>https://dev.to/azure/fetching-teams-user-info-from-microsoft-graph-with-teamsfx-sdk-301c</link>
      <guid>https://dev.to/azure/fetching-teams-user-info-from-microsoft-graph-with-teamsfx-sdk-301c</guid>
      <description>&lt;h2&gt;
  
  
  😘 TL;DR
&lt;/h2&gt;

&lt;p&gt;First of all, this tutorial became far longer than I initially intended, so I decided to include this quick summary of the article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are various tools and SDKs for Teams app development so you need to pick the right &amp;amp; preferred tools!&lt;/li&gt;
&lt;li&gt;TeamsFx is a great tool when you build app that uses Microsoft Graph API for fetching data, such as basic user info&lt;/li&gt;
&lt;li&gt;TeamsFx handles the OAuth 2.0 authorization code grant flow, getting an access token, and use the token to make Graph API calls&lt;/li&gt;
&lt;li&gt;Use the Graph wrapper, &lt;code&gt;client.api(path).get&lt;/code&gt; to make the call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, proceed to the main content!&lt;/p&gt;




&lt;p&gt;In my &lt;a href="https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g"&gt;previous tutorial&lt;/a&gt;, I showed you how to use a VS Code extension, Teams Toolkit to start building a Teams bot. In this tutorial, I walk you through the sample bot app from Toolkit and introduce you Microsoft Graph and TeamsFx. But before getting into the code, let me quickly explain about development tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Teams Development Tools
&lt;/h2&gt;

&lt;p&gt;In my other Microsoft Teams-related tutorials, I mentioned &lt;strong&gt;Teams SDK&lt;/strong&gt; to build Tabs core user interface, &lt;strong&gt;Bot Framework&lt;/strong&gt; to build bots and messaging extensions, &lt;strong&gt;Adaptive Cards&lt;/strong&gt; for UI components in messages, and &lt;strong&gt;Teams Toolkit&lt;/strong&gt; VSCode extension for quick scaffolding all types of Teams apps.&lt;/p&gt;

&lt;p&gt;Some of the tools are not only created for Teams development, but for multiple Microsoft products. Here's a quick table of available tools for Teams:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;What it does for Teams app development&lt;/th&gt;
&lt;th&gt;What else it is used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://docs.microsoft.com/javascript/api/overview/msteams-client?view=msteams-client-js-latest&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Teams SDK&lt;/a&gt; (Teams.js)&lt;/td&gt;
&lt;td&gt;Teams Client SDK&lt;/td&gt;
&lt;td&gt;Tabs development (Front-end)&lt;/td&gt;
&lt;td&gt;(Teams-specific)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://dev.botframework.com/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Bot Framework&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Bot SDK&lt;/td&gt;
&lt;td&gt;Teams bots development&lt;/td&gt;
&lt;td&gt;Web &amp;amp; mobile chat, Skype, Facebook, Amazon Alexa, Slack, Twilio, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://adaptivecards.io/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Adaptive Cards&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Platform-agnostic UI snippets (JSON)&lt;/td&gt;
&lt;td&gt;Rich-format messages &amp;amp; cards&lt;/td&gt;
&lt;td&gt;Web &amp;amp; mobile UI, Outlook messages, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.microsoft.com/microsoftteams/platform/concepts/build-and-test/app-studio-overview/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;App Studio&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Visual tool&lt;/td&gt;
&lt;td&gt;Create &amp;amp; configure Teams app packages&lt;/td&gt;
&lt;td&gt;(Teams-specific)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.ms-teams-vscode-extension&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Teams Toolkit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;VS Code Extension&lt;/td&gt;
&lt;td&gt;Register &amp;amp; configure app. App scaffold&lt;/td&gt;
&lt;td&gt;(Teams-specific)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.microsoft.com/javascript/api/@microsoft/teamsfx/?view=msteams-client-js-latest&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;TeamsFx&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;SDK &amp;amp; CLI&lt;/td&gt;
&lt;td&gt;Implement identity and access to Graph resources&lt;/td&gt;
&lt;td&gt;(Teams-specific)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.microsoft.com/graph/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Microsoft Graph&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;REST API&lt;/td&gt;
&lt;td&gt;Provides access to data stored across Microsoft 365 services, including Teams&lt;/td&gt;
&lt;td&gt;Access &amp;amp; manage calendar, mail, oneDrive, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://dev.teams.microsoft.com/home" rel="noopener noreferrer"&gt;Developer Portal for Microsoft Teams&lt;/a&gt; (Preview)&lt;/td&gt;
&lt;td&gt;Web tool&lt;/td&gt;
&lt;td&gt;Configurations &amp;amp; references&lt;/td&gt;
&lt;td&gt;(Teams-specific)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;There are more tools you can use for Teams, but I am not covering everything in this tutorial!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Usually during development, you would use a combination of some of them. For example, in this tutorial we are going to use Teams Toolkit, Bot Framework (that includes wrapper methods for Adaptive Cards), and TeamsFx (that includes Graph API wrappers). &lt;/p&gt;

&lt;p&gt;Now, let's start off where we left off in the previous tutorial, &lt;a href="https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g"&gt;Using VS Code Teams Toolkit Extension for Teams App Development&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Using Microsoft Bot Framework
&lt;/h2&gt;

&lt;p&gt;After you build and run the template code from the Toolkit, let's take a look at &lt;strong&gt;bot&lt;/strong&gt; directory, where the bot code is stored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ngd7tbfbq2y3ra1iq7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ngd7tbfbq2y3ra1iq7d.png" alt="Screenshot - VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's walk through the template code together quickly—&lt;/p&gt;

&lt;h3&gt;
  
  
  📄 bot/index.js
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;index.js&lt;/strong&gt;, notice &lt;a href="https://docs.microsoft.com/javascript/api/botbuilder/?view=botbuilder-ts-latest&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;&lt;code&gt;botbuilder&lt;/code&gt;&lt;/a&gt; (Microsoft Bot Framework) is imported.&lt;/p&gt;

&lt;p&gt;This is where the adapter is created so that it allows your bot to communicate with the user and send responses.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BotFrameworkAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ConversationState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MemoryStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;botbuilder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BotFrameworkAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Teams Toolkit already has handled registering your bot to Azure Active Directory so you don't need to manually configure your Bot ID and password&lt;/em&gt; 🙌&lt;/p&gt;

&lt;p&gt;Also, &lt;code&gt;Restify&lt;/code&gt; is set up to HTTP server and routing HTTP requests.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;restify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Listen for incoming requests.&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;processActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To simplify the tutorial, I am not explaining how to manage states, and what &lt;em&gt;turn&lt;/em&gt; means. If you would like to learn the concept of bot, read &lt;a href="https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;How bot works&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  📄 bot/teamsBot.js
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;bot/teamsBot.js&lt;/strong&gt; is the main entry point for the bot.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;TeamsBot&lt;/code&gt; class is being created here. Its &lt;code&gt;run&lt;/code&gt; function is called by the adapter and routed to bot's activity logic through &lt;code&gt;Restify&lt;/code&gt; middleware (from &lt;strong&gt;index.js&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;In the constructor, it overrides some of the &lt;a href="https://docs.microsoft.com/javascript/api/botbuilder/teamsactivityhandler?view=botbuilder-ts-latest&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;&lt;code&gt;TeamsActivityHandler&lt;/code&gt;&lt;/a&gt; methods by extending it to customize bot behavior and message text.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TeamsBot&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TeamsActivityHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conversationState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onMembersAdded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For example, methods overridden are &lt;code&gt;onMessage&lt;/code&gt; and &lt;code&gt;onMembersAdded&lt;/code&gt; in this sample. They register the event handlers for the &lt;code&gt;message&lt;/code&gt; event, emitted for every incoming message activity, and &lt;code&gt;MembersAdded&lt;/code&gt; event emitted when a new member is added to the conversation, respectively.&lt;/p&gt;

&lt;h4&gt;
  
  
  Message event
&lt;/h4&gt;

&lt;p&gt;When a message is sent to bot from a user (like, &lt;code&gt;show&lt;/code&gt; command), &lt;code&gt;onMessage&lt;/code&gt; gets triggered.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialogState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, it runs the &lt;code&gt;Dialog&lt;/code&gt; with the new message Activity.&lt;/p&gt;

&lt;h3&gt;
  
  
  📄 bot/dialogs/mainDialogs.js
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Dialog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DialogSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DialogTurnStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WaterfallDialog&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;botbuilder-dialogs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://docs.microsoft.com/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;dialogs library&lt;/a&gt; 💬 provides a state-based model to manage a long-running conversation with the user. A dialog performs a task that can represent conversational thread. &lt;/p&gt;




&lt;p&gt;Okay, this was a quick walk-through of what some of the code does. Now, let's get to the main topic, &lt;strong&gt;TeamsFx&lt;/strong&gt; and &lt;strong&gt;Graph&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🪅 What is TeamsFx?
&lt;/h2&gt;

&lt;p&gt;TeamsFx is a framework, created to make the integrations of &lt;strong&gt;Microsoft Graph API&lt;/strong&gt; and implementing identity and access with Teams easier. For example, it handles the OAuth 2.0 authorization code grant flow, getting an access token, and use the token to make Graph API calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microsoft Graph API
&lt;/h3&gt;

&lt;p&gt;So what is &lt;a href="https://docs.microsoft.com/graph/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Microsoft Graph API&lt;/a&gt;, first of all? It is a REST API lets you to connect the data from Microsoft 365 services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fgraph%2Fimages%2Fmicrosoft-graph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fgraph%2Fimages%2Fmicrosoft-graph.png" alt="Microsoft Graph API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;M365 platform holds various people-centric data and insights across the Microsoft cloud services, including Teams, Outlook, Calendars, etc. It means whenever you want to access to the data within your Teams app, you need to use Graph to access the data. &lt;/p&gt;

&lt;p&gt;For example, in this sample app, when a user asks a bot to display the user's info with the &lt;code&gt;show&lt;/code&gt; command, the app make an API call to fetch the data from Graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  🪅 Using TeamsFx to call Graph API
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;bot/dialogs/mainDialogs.js&lt;/strong&gt;, both TeamsFx and Graph libraries are imported:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createMicrosoftGraphClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnBehalfOfUserCredential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TeamsBotSsoPrompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@microsoft/teamsfx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ResponseType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@microsoft/microsoft-graph-client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  🔏 User Authentication &amp;amp; Authorization
&lt;/h3&gt;

&lt;p&gt;The app creates and authenticates a &lt;code&gt;MicrosoftGraphClient&lt;/code&gt; by calling &lt;code&gt;loadConfiguration()&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then, a new instance of &lt;code&gt;TeamsBotSsoPrompt&lt;/code&gt; is added as a named dialog. &lt;code&gt;TeamsBotSsoPrompt&lt;/code&gt; is integrated with Bot Framework to simplify the authentication process for bots:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;loadConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;dialogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TeamsBotSsoPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TeamsBotSsoPrompt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User.Read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;scopes&lt;/code&gt; are the types of permission it requires to call Graph APIs for Teams. The resource-specific permissions are granular and define what an application can do within a specific resource.&lt;/p&gt;

&lt;p&gt;There are various permission scopes that can &lt;em&gt;read&lt;/em&gt; or &lt;em&gt;write&lt;/em&gt; (create, edit, delete). For instance, &lt;code&gt;User.Read&lt;/code&gt; is the scope needed to read users info, as the name suggests. And to enable the permissions, the app must ask the user for their consent.&lt;/p&gt;

&lt;p&gt;This operation creates a new prompt that leverages Teams Single Sign On (SSO) support for bot to automatically sign in user to receive OAuth token 🏅.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--h3bHmAbq--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r80t4cvr4fdxt9vyx3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--h3bHmAbq--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r80t4cvr4fdxt9vyx3k.png" alt="Screenshot - permissions dialog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Authentication and authorization are big topics here. I would need another tutorial to explain deeply about Microsoft identity platform. In the meantime, please read &lt;a href="https://docs.microsoft.com/graph/auth/auth-concepts/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Authentication and authorization basics for Microsoft Graph&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📇 Calling Graph API
&lt;/h3&gt;

&lt;p&gt;In the app, when a user sends the "show" command to the bot, the app calls an API from Graph to fetch the user info. (The app asks the user a permission by popping up a SSO window before fetching the user's info, as explained in the previous section.)&lt;/p&gt;

&lt;p&gt;Every API call requires the access token 🏅 that has been acquired at the SSO sign-in process. (The token is attached in the Authorization header of the request). &lt;/p&gt;

&lt;p&gt;Also, to access the Microsoft Graph API for Teams, you will need the Teams credentials to do authentication to create a Graph client object.&lt;/p&gt;

&lt;p&gt;3 credential classes that are used to help simplifying authentication in TeamsFx:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;TeamsUserCredential&lt;/code&gt; - Teams current user's identity. Using this credential will request user consent at the first time. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;M365TenantCredential&lt;/code&gt; - Microsoft 365 tenant identity. It is usually used when user is not involved like time-triggered automation job. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OnBehalfOfUserCredential&lt;/code&gt; - on-behalf-of flow. It needs an access token and you can get a new token for different scope. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For bot scenarios, we are using &lt;code&gt;OnBehalfOfUserCredential&lt;/code&gt; here:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oboCredential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OnBehalfOfUserCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ssoToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;graphClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMicrosoftGraphClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oboCredential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User.Read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, you have authentication setup and an instance of Graph client, you can finally begin to make calls to the service! &lt;/p&gt;

&lt;p&gt;This is how you can fetch the basic user information, then making the bot to send a message to Teams client:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;graphClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stepContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`You're logged in as &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and your job title is: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jobTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;...&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now this is the simplified flow of what you have just learned:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx77ebyoyygnxmij1cuh2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx77ebyoyygnxmij1cuh2.png" alt="Teams bot flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g#running-a-sample-bot-locally"&gt;Build and run&lt;/a&gt; on Teams client if you haven't. Try the &lt;code&gt;show&lt;/code&gt; command to ask the bot to display your info. &lt;br&gt;
When everything goes well, this is how it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjn7n2z1dy9vx6557lvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjn7n2z1dy9vx6557lvu.png" alt="Screenshot - bot showing user info"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ta-da 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧺 More with Graph
&lt;/h2&gt;

&lt;p&gt;Try making more Graph calls with the &lt;code&gt;api&lt;/code&gt; method. All requests start with &lt;code&gt;client.api(path)&lt;/code&gt; and end with an action, &lt;code&gt;get&lt;/code&gt; or &lt;code&gt;post&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;To get the Teams group the user have joined:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;graphClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;me/joinedTeams&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response gives you a list of groups including the group IDs.&lt;/p&gt;

&lt;p&gt;To get the members of a Teams group:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;graphClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;groups/{Teams group ID}/members&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Also, try &lt;a href="https://developer.microsoft.com/graph/graph-explorer/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Graph Explorer&lt;/a&gt; to test out the REST API and visualize the response!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rd4gan1mhpdmm4jzuyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rd4gan1mhpdmm4jzuyx.png" alt="Screenshot - Graph Explorer"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I hope you enjoyed the tutorial. There are many things you would want to know, such as concepts of bots, OAuth, identity management, etc. but I tried not to make this tutorial too wordy by flooding with info, so I simplified everything by not diving deep into the details on purpose. But hopefully, this tutorial still made sense to you!&lt;/p&gt;

&lt;p&gt;If you would like to dive deep, please check out the docs and code repos listed below!&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.botframework.com/?T.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Microsoft Bot Frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bot Services Documentation - &lt;a href="https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0&amp;amp;tabs=javascript&amp;amp;WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;How bot works?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/javascript/api/@microsoft/teamsfx/?view=msteams-client-js-latest&amp;amp;T.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;TeamsFx SDK references&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/OfficeDev/TeamsFx" rel="noopener noreferrer"&gt;TeamsFx GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/graph/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Microsoft Graph API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/graph/auth/auth-concepts/?WT.mc_id=m365-35902-timura" rel="noopener noreferrer"&gt;Authentication and authorization basics for Microsoft Graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>msteams</category>
      <category>tutorial</category>
      <category>node</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Using VS Code Teams Toolkit Extension for Teams App Development</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Wed, 21 Jul 2021 22:12:08 +0000</pubDate>
      <link>https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g</link>
      <guid>https://dev.to/azure/using-vs-code-toolkit-for-teams-app-development-2o0g</guid>
      <description>&lt;p&gt;In my previous posts related to the Microsoft Teams developer platform, I introduced a few of Teams app types and how to build your first &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k/?WT.mc_id=m365-9173-timura"&gt;tabs&lt;/a&gt;, &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m/?WT.mc_id=m365-9173-timura"&gt;bots&lt;/a&gt;, and &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-3-messaging-action-5ejc?WT.mc_id=m365-9173-timura"&gt;message extensions&lt;/a&gt;. These tutorials instructed you to use &lt;strong&gt;App Studio&lt;/strong&gt; for manual configurations and minimal local setup, to focus on familiarizing you with the concept of Teams app features.&lt;/p&gt;

&lt;p&gt;However, in this tutorial, I am showing another way to develop, using a newly introduced developer tool, called &lt;a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.ms-teams-vscode-extension&amp;amp;WT.mc_id=m365-35901-timura" rel="noopener noreferrer"&gt;&lt;strong&gt;Teams Toolkit&lt;/strong&gt; (Preview)&lt;/a&gt; for VS Code, which was created to help you build and deploy Teams apps with integrated identity, access to cloud storage, data from &lt;a href="https://docs.microsoft.com/en-us/graph/?WT.mc_id=m365-35901-timura" rel="noopener noreferrer"&gt;Microsoft Graph&lt;/a&gt;, and other services in Azure and M365. &lt;/p&gt;




&lt;p&gt;Before you begin, let's check if you have set up your working environment to develop on Teams. &lt;/p&gt;

&lt;h2&gt;
  
  
  📓 Prerequisites
&lt;/h2&gt;

&lt;p&gt;First, make sure if your Teams client allows you to "sideload" custom apps. Check &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/prepare-your-o365-tenant#enable-custom-teams-apps-and-turn-on-custom-app-uploading/?WT.mc_id=m365-35901-timura" rel="noopener noreferrer"&gt;Enable custom Teams apps and turn on custom app uploading&lt;/a&gt; before you begin.  &lt;/p&gt;

&lt;p&gt;Or you can sign up for &lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program/?WT.mc_id=m365-35901-timura" rel="noopener noreferrer"&gt;&lt;strong&gt;Microsoft 365 developer program&lt;/strong&gt;&lt;/a&gt;, a free, renewable subscription that comes with a developer tenant sandbox and sample data pack, like mock user data!&lt;/p&gt;

&lt;p&gt;And if you haven't using it already, get the latest version of &lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;. (Earlier versions might not work with the toolkit.) &lt;/p&gt;

&lt;h2&gt;
  
  
  🖥 Installing Teams Toolkit
&lt;/h2&gt;

&lt;p&gt;Launch VS Code and now install an extension that helps you develop Teams apps.  &lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Extensions&lt;/strong&gt; icon on the left Activity Bar and install the &lt;strong&gt;Microsoft Teams Toolkit&lt;/strong&gt;. If you see two different versions of Teams, Toolkit, make sure to select the "Preview" version 2.x for this tutorial: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foepw07irtbmr2gasa8mv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foepw07irtbmr2gasa8mv.png" alt="Screenshot - Find Toolkit extension in VS Code and install"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Optional Tools
&lt;/h3&gt;

&lt;p&gt;The following tools will be installed by the Teams Toolkit extension as you need. &lt;em&gt;However, if using Linux (including WSL), you need to install these tools before using&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;Azure Functions Core Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ngrok.com/download" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧰 Creating New Project with Toolkit
&lt;/h2&gt;

&lt;p&gt;Select &lt;strong&gt;Microsoft Teams&lt;/strong&gt; icon on the left Activity Bar and click &lt;strong&gt;Create New Project&lt;/strong&gt;. At the popup, select &lt;strong&gt;Create a new Teams app&lt;/strong&gt; : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhx19vq46ir3xemavuoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhx19vq46ir3xemavuoh.png" alt="Screenshot - Create a new app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Select capabilities section, select one. For this tutorial (and for &lt;a href="https://dev.to/azure/fetching-teams-user-info-from-microsoft-graph-with-teamsfx-sdk-301c"&gt;the next tutorial&lt;/a&gt;), let's pick &lt;strong&gt;Bot&lt;/strong&gt;, and deselect Tab and select &lt;strong&gt;OK&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7xaqwjpc1nb1svqvnwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7xaqwjpc1nb1svqvnwu.png" alt="Screenshot - Create a bot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Bot registration section, select &lt;strong&gt;Create a new bot registration&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91zqldpk9843yuxa02m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91zqldpk9843yuxa02m5.png" alt="Screenshot - register a bot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Programming Language section, select &lt;strong&gt;JavaScript&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcv1o2j28xzi1pct4wsf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcv1o2j28xzi1pct4wsf2.png" alt="Screenshot - select JS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select a workspace. A new folder will be created within your workspace for the project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j3fwp8z8ol2m5mtblty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j3fwp8z8ol2m5mtblty.png" alt="Screenshot - select workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter some name for your app. Press Enter to continue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeextn5rcy9eyxtofalq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeextn5rcy9eyxtofalq.png" alt="Screenshot - enter app name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will take some time to set it up for you.&lt;/p&gt;

&lt;p&gt;In this setup process, the toolkit is preparing these for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;registering an Azure Active Directory Application within the M365 tenant&lt;/li&gt;
&lt;li&gt;creating an app manifest&lt;/li&gt;
&lt;li&gt;running API locally using Azure Functions Core Tools to support your app&lt;/li&gt;
&lt;li&gt;installing and setting up &lt;em&gt;ngrok&lt;/em&gt;, to securely tunnel from your localhost to the Teams client&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤖 Running a Sample Bot Locally
&lt;/h2&gt;

&lt;p&gt;Once your project is set up, take a look around and see how the template app looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqxamoak9u43z293wls0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqxamoak9u43z293wls0.png" alt="Screenshot - code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But for now, let's just build this sample app and run it locally. &lt;/p&gt;

&lt;p&gt;Press &lt;strong&gt;F5&lt;/strong&gt; key to enable the debug mode. &lt;/p&gt;

&lt;p&gt;Alternatively, click the debug icon from the side menu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay6zkkyuzm0q3qwlzkjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay6zkkyuzm0q3qwlzkjx.png" alt="Screenshot - debug and run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This can take up a few minutes to complete as all dependencies are downloaded and the app is built for the first time.&lt;/p&gt;

&lt;p&gt;Once it is done, Teams web client will be automatically opened in a browser window. Install it locally by clicking &lt;strong&gt;Add&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgi67d55de01zpucu0fs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgi67d55de01zpucu0fs.png" alt="Screenshot - Teams app being installed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the app is installed, try the bot by typing a command or pick from the menu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz6purzuchvxw2cloa5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz6purzuchvxw2cloa5u.png" alt="Screenshot - Teams app running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔏 Granting User Permissions
&lt;/h3&gt;

&lt;p&gt;When you try &lt;code&gt;show&lt;/code&gt; command, you should notice the app asks your permission to display your information like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d2068p9bdq1amrntq5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d2068p9bdq1amrntq5k.png" alt="Screenshot - Teams app permission"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and once you hit &lt;strong&gt;Continue&lt;/strong&gt;, it will open an authorization screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r80t4cvr4fdxt9vyx3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r80t4cvr4fdxt9vyx3k.png" alt="Alt Text - user authorization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, it means that your app (and any 3rd party apps!) just cannot automatically grab a user's information without the user's consent!&lt;/p&gt;




&lt;p&gt;In next tutorial, I will explain about Microsoft Graph to access user information and how you can implement it for Teams, so stay tuned 👋&lt;/p&gt;

</description>
      <category>msteams</category>
      <category>m365</category>
      <category>vscode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Support Web Monetization and HODL! — How to receive micropayment in $BTC (or $Ɖoge) on your website</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Sun, 21 Feb 2021 23:38:34 +0000</pubDate>
      <link>https://dev.to/girlie_mac/support-web-monetization-and-hodl-how-to-receive-micropayment-in-btc-or-oge-on-your-website-5c5d</link>
      <guid>https://dev.to/girlie_mac/support-web-monetization-and-hodl-how-to-receive-micropayment-in-btc-or-oge-on-your-website-5c5d</guid>
      <description>&lt;p&gt;👋 &lt;em&gt;You may think this a clickbait. But no, this post really is about web platform!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As I am writing this on Feb 20, 2021, Bitcoin (&lt;a href="https://www.fool.com/quote/crypto/bitcoin/btc/"&gt;CRYPTO:BTC&lt;/a&gt;) has hit a $1 trillion market cap. Investors who thought it was a joke have started jumped into the cryptocurrency frenzy. &lt;/p&gt;

&lt;p&gt;Although the ideas of decentralized market and blockchain are fascinating, I didn’t think the value of BTC would increase much, so I have spent them on things like yoga pants and flights to Europe. I try not to think about how much worth it in today's rate. There are just too many what-if scenarios in my life. (BTW, the economy-class ticket I got was about 1.3 BTC. I let you figure it out.)&lt;/p&gt;

&lt;p&gt;Now friends are asking me about advice on cryptocurrency and &lt;a href="https://www.coinbase.com/join/girlie_mac"&gt;Coinbase referrals&lt;/a&gt;, however, because I can be the worst financial advisor to ruin your life, I am not going to tell you how to invest, or even how to mine in this article, instead, I am going to tell you about &lt;strong&gt;Web Monetization&lt;/strong&gt; and how to receive micropayments in $BTC and other currencies including various cryptocurrencies, like $DOGE if you want, through your website.&lt;/p&gt;

&lt;p&gt;I may sound like I am selling you snake oil, but I just thought this may be a good opportunity to talk about the web standard topic. &lt;/p&gt;




&lt;h2&gt;
  
  
  Web Monetization &amp;amp; Interledger
&lt;/h2&gt;

&lt;p&gt;According to the draft submitted to W3C, &lt;a href="https://webmonetization.org/specification.html"&gt;Web Monetization&lt;/a&gt; is an API that allows websites to request small payments from users facilitated by the browser and the user's Web Monetization provider.&lt;/p&gt;

&lt;p&gt;In a nutshell, Web Monetization is an open web API, consists of HTML, JavaScript API, and uses the &lt;a href="https://interledger.org/"&gt;Interledger protocol&lt;/a&gt;, an open protocol for moving money and enabling payments. &lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Web Monetization
&lt;/h2&gt;

&lt;p&gt;Although implementation for browsers is straight-forward, it requires some prerequisits as currently, you need (1) a Web Monetization service provider and (2) an Interledger Protocol-enabled wallet to monetize on web.&lt;/p&gt;

&lt;p&gt;The services I personally use to implement Web Monetization are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://coil.com"&gt;Coil&lt;/a&gt; - Web Monetization service provider&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://uphold.com/signup?referral=5c133755de"&gt;Uphold&lt;/a&gt; - ILP-enabled wallet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How &lt;strong&gt;Coil&lt;/strong&gt; works is that is checks if the website is web monetized, and if it does, stream the payment to the site. A small amount is paid by Coil members, who pay a flat fee to access exclusive content and ad-free experiences. Coil provides browser extensions for browsers including Chrome, Edge, and Firefox, while &lt;a href="https://www.pumabrowser.com/"&gt;&lt;strong&gt;Puma browser&lt;/strong&gt;&lt;/a&gt; is natively powered on Coil and supports Web Monetization API out of the box.&lt;/p&gt;

&lt;p&gt;And &lt;strong&gt;Uphold&lt;/strong&gt; is a digital wallet that allows you to receive payments with an Interledger payment pointer. This is where you can receive the payment also sell, buy, and trade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up Your Wallet
&lt;/h3&gt;

&lt;p&gt;Coil supports multiple wallets, but I am using Uphold to generate your Interledger payment pointer here.&lt;/p&gt;

&lt;p&gt;First, open an &lt;a href="https://uphold.com/signup?referral=5c133755de"&gt;Uphold&lt;/a&gt; account. &lt;/p&gt;

&lt;p&gt;Once you signed up and all, you are going to generate an ILP address (Interledger payment pointer). &lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;Transact&lt;/strong&gt;, then from the &lt;strong&gt;Anything to Anything&lt;/strong&gt; (Right pane), select &lt;strong&gt;From&lt;/strong&gt; dropdown menu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hm16tpu---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydu682fq234lzk7dmn31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hm16tpu---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydu682fq234lzk7dmn31.png" alt="Screenshot - Uphold 1" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Interledger&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--85ohMvT0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfsr0phc3og8jyx5z3ej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--85ohMvT0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfsr0phc3og8jyx5z3ej.png" alt="Screenshot - Uphold 2" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then pick a currency of your choice— USD, BTC, ETH, XRP, DOGE… there are 27 fiat currencies and&lt;br&gt;
34 Cryptocurrencies to choose from:&lt;/p&gt;

&lt;p&gt;![Screenshot - Uphold 3]!(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6c7z5t7bp02j871sc0gc.png"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6c7z5t7bp02j871sc0gc.png&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Copy the address that looks like &lt;code&gt;$ilp.uphold.com/SoMethIngLiKEthis0&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3tNweJ7e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wecd2dkomnpx82b1zgzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3tNweJ7e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wecd2dkomnpx82b1zgzv.png" alt="Screenshot - Uphold 4" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will need the address in Coil (the next step) and in your HTML code later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up Coil
&lt;/h3&gt;

&lt;p&gt;There are two membership types— Coil membership to support web-monetized content and creator membership for monetization. I am walking you through the latter.&lt;/p&gt;

&lt;p&gt;First, sign up for a &lt;a href="https://coil.com/creator"&gt;&lt;strong&gt;Coil creator account&lt;/strong&gt;&lt;/a&gt; and click &lt;strong&gt;Start monetizing. It's free&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;Once you created your account (and verified your email etc.), you will need to set up your payout wallet. &lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://coil.com/settings/payouts"&gt;&lt;strong&gt;Payout&lt;/strong&gt;&lt;/a&gt;, click &lt;strong&gt;Setup&lt;/strong&gt; under &lt;strong&gt;Uphold&lt;/strong&gt; (unless you chose Gatehub as your wallet):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fp667x4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atlhmbh3h0zefdy9s6t1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fp667x4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atlhmbh3h0zefdy9s6t1.png" alt="Screenshot - Coil 1" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and enter the ILP address that you generated at Uphold and save:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Yv4XfZ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sns1siqm2rmve80wc6wh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Yv4XfZ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sns1siqm2rmve80wc6wh.png" alt="Screenshot - Coil 2" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you are going to include a meta tag with the information on your website to finalize.&lt;/p&gt;
&lt;h2&gt;
  
  
  Monetizing Your Web
&lt;/h2&gt;

&lt;p&gt;If you already have some website or web apps, you are ready to monetize. All you need is to include the &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; in your head of HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Welcome to My Homepage&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt;
     &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"monetization"&lt;/span&gt;
     &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"$ilp.uphold.com/6NxbkHNq9N84"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to use your own ILP address as the meta content, unless you want me to receive all of your payment. Then, deploy your web and you are ready to monetize 💰&lt;/p&gt;

&lt;h3&gt;
  
  
  Monetizing Your Content Here on Dev.to
&lt;/h3&gt;

&lt;p&gt;Even if you don’t have your own websites, some content platforms do support Web Monetization. Take a look at the &lt;a href="https://help.coil.com/docs/monetize/content/platforms"&gt;list of providers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are a writer here on Dev.to too, you can include your ILP address to monetize your content there too. &lt;/p&gt;

&lt;p&gt;Sign in and go to the &lt;a href="https://dev.to/settings/misc"&gt;&lt;strong&gt;Settings&lt;/strong&gt;&lt;/a&gt; &amp;gt; &lt;strong&gt;Extensions&lt;/strong&gt; &amp;gt; &lt;strong&gt;Web monetization&lt;/strong&gt;, and enter your ILP address there and save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A6xTlZjr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/recvox39sxwcxjn6x8d4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A6xTlZjr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/recvox39sxwcxjn6x8d4.png" alt="devto" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it. &lt;br&gt;
Now all you need is to wait to get paid in BTC (or whatever you picked) and HODL ;-)&lt;/p&gt;

&lt;p&gt;I hope you enjoyed the article. Web platform to the moon 🚀🌕&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>webmonetization</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>Beginners Guide to MS Teams Development #3 Messaging Action</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Tue, 03 Nov 2020 22:56:33 +0000</pubDate>
      <link>https://dev.to/azure/beginners-guide-to-ms-teams-development-3-messaging-action-5ejc</link>
      <guid>https://dev.to/azure/beginners-guide-to-ms-teams-development-3-messaging-action-5ejc</guid>
      <description>&lt;p&gt;Hello, I hope you enjoyed the previous two tutorials on how to get started with Microsoft Teams development, (Developing &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k/?WT.mc_id=m365-9173-timura"&gt;Tabs on Teams&lt;/a&gt; and &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m/?WT.mc_id=m365-9173-timura"&gt;Bots&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the third one of the beginner series, and this time, I will walk you through how to invoke an action from a message.&lt;/p&gt;

&lt;p&gt;There are many different paths to learn how to build Teams apps, and this tutorial uses a bare-minimum code and minimal toolsets. Also, this tutorial is independent of the hosting environment, so I am not starting the process with the Azure setup, and basically, this should run on any environment, as long as you can run a browser. &lt;/p&gt;




&lt;p&gt;In this tutorial, I am introducing another Teams platform feature, &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/what-are-messaging-extensions/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;Messaging Extensions&lt;/a&gt;. This feature comes with two different types, Action and Search, and it depends on how it interact with the UI elements and flows.&lt;/p&gt;

&lt;p&gt;In this tutorial, I am showing how to built an &lt;strong&gt;Action command&lt;/strong&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Teams features: Messaging Extensions - Action Command
&lt;/h1&gt;

&lt;p&gt;Action commands allow you to present your users with a modal popup to collect or display information. When they submit the form, your web service can respond by inserting a message into the conversation directly, or by inserting a message into the compose message area and allowing the user to submit the message. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Ftask-module.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Ftask-module.png" alt="Teams action command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Morse Code message action
&lt;/h2&gt;

&lt;p&gt;The app we are going to build invokes an action from a user message, extract the text, and convert it to a Morse code! &lt;/p&gt;

&lt;p&gt;How the app works is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user hovers a message to open the message menu, and choose the Morse Bot from the menu&lt;/li&gt;
&lt;li&gt;When the user action is trigered, a payload is sent to your messaging endpoint (/api/messages)&lt;/li&gt;
&lt;li&gt;This invokes the fetchTask - the message text data is extracted&lt;/li&gt;
&lt;li&gt;A popup dialog is displayed. The user can edit the text content if they want, then submit&lt;/li&gt;
&lt;li&gt;The app translate the text into a morde code, and display the content as a reply&lt;/li&gt;
&lt;li&gt;The user can send the result to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is how the result would look like:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkvwq8o7fix7qowgeuoml.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkvwq8o7fix7qowgeuoml.gif" alt="Teams app gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  📓 Prerequisites
&lt;/h3&gt;

&lt;p&gt;To be able to install apps to Teams, your organization's admin needs to grant permission.&lt;/p&gt;

&lt;p&gt;Otherwise, you can sign up for &lt;strong&gt;Microsoft 365 developer program&lt;/strong&gt;, a free, renewable subscription that comes with a developer tenant sandbox and sample data pack, like mock user data!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permission to develop on Teams or developer tenant (&lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Sign up for M365 developer program!&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;App Studio - look for the app from the Apps menu in Teams client and install to your workspace&lt;/li&gt;
&lt;li&gt;Experience with Node.js and basic understanding of &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  👾 Technology to be used in this tutorial
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.botframework.com/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Microsoft Bot Framework&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://adaptivecards.io/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;Adaptive Cards&lt;/a&gt; for building some UI snippets&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Building an action
&lt;/h2&gt;
&lt;h3&gt;
  
  
  🎏 Grabbing the code sample
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I am using the 3rd party tool, &lt;a href="https://glitch.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Glitch&lt;/strong&gt;&lt;/a&gt; to host and run this project and the rest of the tutorial series. &lt;em&gt;For a little more details what Glitch is and why I am using it, please refer my &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m"&gt;previous tutorial&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, let's just &lt;a href="https://glitch.com/edit/#!/remix/msteams-msg-extension-action" rel="noopener noreferrer"&gt;click this Glitch link to &lt;em&gt;remix&lt;/em&gt; the project&lt;/a&gt;. Remixing is like the forking a repo on GitHub, so it generates a copy of the project for you, so you can modify the code in the way you want without messing with the original 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://glitch.com/edit/#!/remix/msteams-msg-extension-action" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.glitch.com%2F2703baf2-b643-4da7-ab91-7ee2a2d00b5b%252Fremix-button.svg" alt="Remix on Glitch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get your own project repo, it serves up the app automatically and you get your own web server URL. You will need the URL when you are setting up an app with App Studio later.&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ App Configuration: Creating App Manifest with App Studio
&lt;/h3&gt;

&lt;p&gt;The basic idea of App Package for Teams, please refer to the  &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m"&gt;previous tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  🎛 Using App Studio
&lt;/h3&gt;

&lt;p&gt;Open &lt;strong&gt;App Studio&lt;/strong&gt; app in Teams client. &lt;/p&gt;

&lt;p&gt;In App Studio, click the Manifest Editor tab from the top, then select &lt;strong&gt;Create a new app&lt;/strong&gt; and fill out all the required fields including the Bot names, descriptions, etc.&lt;/p&gt;

&lt;p&gt;Then, generate an App ID.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdhavjptelsoes0697nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdhavjptelsoes0697nc.png" alt="Teams App Studio"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🔖 Configuring a Messaging Extension
&lt;/h3&gt;

&lt;p&gt;From the left menu, select Capabilities &amp;gt; &lt;strong&gt;Massaging Extensions&lt;/strong&gt;. Go ahead and click the Setup button to set up.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fogfqgbe5wafpurrhlyt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fogfqgbe5wafpurrhlyt1.png" alt="App Studio"&gt;&lt;/a&gt;&lt;br&gt;
Give your app a name.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmo63x8sqnrdz9wj7liqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmo63x8sqnrdz9wj7liqx.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🔐 App credentials
&lt;/h3&gt;

&lt;p&gt;Copy the ID next to your bot name (something looks like &lt;code&gt;2cd53e8a-e698-4exx-...&lt;/code&gt;) and paste it as an environment variable in your &lt;em&gt;.env&lt;/em&gt; file, which is supposed to be a hidden file (Rename the &lt;code&gt;.env-sample&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;App Passwords&lt;/strong&gt;, generate a new password, and copy it. Then paste it in your &lt;em&gt;.env&lt;/em&gt; file.&lt;/p&gt;

&lt;p&gt;These credentials are used to initialize your bot adapter. (See index.js).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpnx9qfidui79ebzayjpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpnx9qfidui79ebzayjpb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Step 3 in the screen image above will be explained at the next step.)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🎬 Configuring an Action
&lt;/h3&gt;

&lt;p&gt;At &lt;strong&gt;Messaging Endpoint&lt;/strong&gt;, enter your web server URL, like, &lt;code&gt;https://[your project].glitch.me/api/messages&lt;/code&gt; if you have remixed the sample repo.&lt;/p&gt;

&lt;p&gt;Scroll to &lt;strong&gt;Command&lt;/strong&gt; and click "Add".&lt;/p&gt;

&lt;p&gt;In the dialog box -&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select "Allow users to trigger actions in external service..."&lt;/li&gt;
&lt;li&gt;Select "Fetch a dynamic set of parameters from your bot"&lt;/li&gt;
&lt;li&gt;Fill out the command ID and title text. Click "Massage" (Unselect other checkboxes if they are pre-selected). Leave the rest blank, then save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx6zpdviv4xdq3bn90prz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx6zpdviv4xdq3bn90prz.png" alt="App Studio"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9obiddhhx1bbbhq93s0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9obiddhhx1bbbhq93s0v.png" alt="App Studio"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foi5jelvbgswn1h1w0652.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foi5jelvbgswn1h1w0652.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  📦 Installing the app manifest package
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Finish &amp;gt; Test and distribute&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you get any errors, go fix it, otherwise, click &lt;strong&gt;Install&lt;/strong&gt; your client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcyokhzulqi44lpdkj6p4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcyokhzulqi44lpdkj6p4.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also download the zip file that contains &lt;code&gt;manifest.json&lt;/code&gt;, and two icon images to install later or distribute.&lt;/p&gt;

&lt;p&gt;As long as you remixed the code sample, the bot should work already. But let me quickly explain how it is coded before trying the bot.&lt;/p&gt;
&lt;h2&gt;
  
  
  🤖 Microsoft Bot Framework
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.botframework.com/" rel="noopener noreferrer"&gt;Microsoft Bot Framework&lt;/a&gt; is an open source SDK that allows you to build intelligent, enterprise-grade bots. &lt;/p&gt;

&lt;p&gt;This SDK is a powerful platform that not only for Teams, but also designed to work for wide types of chat bots, including web &amp;amp; mobile chat, Skype, Facebook, Amazon Alexa, Slack, Twilio, and more!&lt;/p&gt;
&lt;h3&gt;
  
  
  🔧 Initiating the bot service
&lt;/h3&gt;

&lt;p&gt;First, there are two JS files in the Glitch code sample repo, &lt;strong&gt;index.js&lt;/strong&gt; and &lt;strong&gt;bots.js&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;I am using Express to set up an HTTP server and routing HTTP requests. And the way to initiate the service is the same as &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m"&gt;the previous Bots tutorial&lt;/a&gt;, but this is the recap of the initialization, and creating a bot adapter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import bot services&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BotFrameworkAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;botbuilder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Bot's main dialog&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReverseBot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// App credentials from .env&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BotFrameworkAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MicrosoftAppId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MicrosoftAppPassword&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Create the main dialog&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myBot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MorseBot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: In this example, I am using botbuilder version 4.10.0. If your code doesn't work as expected, check the version you are using!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🦉 Forwarding requests to the bot logic
&lt;/h3&gt;

&lt;p&gt;Use Express to handle the routing to listen for incoming requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/messages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;processActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;myBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have set up the URL in App Studio in the previous step. The &lt;code&gt;/api/messages&lt;/code&gt; is your application’s endpoint URL to respond to client requests. &lt;/p&gt;

&lt;h3&gt;
  
  
  🙋‍♀️ Handling the request
&lt;/h3&gt;

&lt;p&gt;Once a request is received at the endpoint and forwarded to the bot logic, your app receive the context of the request, then create a custom reply in &lt;strong&gt;bots.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;See the &lt;code&gt;TeamsActivityHandler&lt;/code&gt; is extended to create an appropriate handler for the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MorseBot&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TeamsActivityHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Triggers when the message action is invoked by a user&lt;/span&gt;
  &lt;span class="nf"&gt;handleTeamsMessagingExtensionFetchTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/*
      We're going to create an adaptive card UI (modal dialog) here.
      In the dialog, the user confirms what text to be encoded to Morse code.
    */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Triggers when the dialog box is submitted from the FetchTask&lt;/span&gt;
  &lt;span class="nf"&gt;handleTeamsMessagingExtensionSubmitAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// display the result &lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;TeamsActivityHandler&lt;/code&gt; is a Teams specific class that handles messages- such as messages events and sending replies. &lt;/p&gt;

&lt;p&gt;In this scenario, when a user triggers an action from a message, &lt;code&gt;handleTeamsMessagingExtensionFetchTask&lt;/code&gt; gets invoked, so your bot received the information about the message when the action was made from.&lt;/p&gt;

&lt;p&gt;You can learn more about it at &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/how-to/action-commands/create-task-module?tabs=javascript/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;Create and send the task module&lt;/a&gt; on Teams documentation&lt;/p&gt;

&lt;h3&gt;
  
  
  📇 Displaying a modal dialog with Adaptive Cards
&lt;/h3&gt;

&lt;p&gt;The dialog UI is created with &lt;a href="https://adaptivecards.io/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;&lt;strong&gt;Adaptive Cards&lt;/strong&gt;&lt;/a&gt;, which is a Microsoft open source to build snippets of UI in JSON, and can be used in Microsoft Teams, Outlook Actionable Messages, Cortana Skills, etc.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;handleTeamsMessagingExtensionFetchTask&lt;/code&gt; is invoked, get the message content text, and display it in a Adaptive card as a modal dialog, as the response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3de82bu7wbr01t8n26gg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3de82bu7wbr01t8n26gg.png" alt="Adaptive Card in Team"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To defining an Adaptive card and the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AdaptiveCard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TextBlock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The message to be encoded to Morse code:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bolder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editedMessage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Input.Text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;submitLocation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messagingExtensionFetchTask&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Encode to Morse!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Action.Submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adaptiveCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CardFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;adaptiveCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;continue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;adaptiveCard&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am displaying the extracted message text in the &lt;code&gt;type: 'Input.Text'&lt;/code&gt; so that the user can edit the text to be Morse-coded!&lt;/p&gt;

&lt;p&gt;To view the full code, please see the &lt;strong&gt;bot.js&lt;/strong&gt; file in the code sample in Glitch.&lt;/p&gt;

&lt;h3&gt;
  
  
  📮 Handling the user submission
&lt;/h3&gt;

&lt;p&gt;Once a user submits the task module, &lt;code&gt;handleTeamsMessagingExtensionSubmitAction&lt;/code&gt; gets triggered and your web service will receive an object with the command id and parameter values set.&lt;/p&gt;

&lt;p&gt;In this sample code, it just checks if the custom data, &lt;code&gt;editedMessage&lt;/code&gt; is there. And if so, grab the value (should be a string) and convert it and display the content to be composed as a new message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleTeamsMessagingExtensionSubmitAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editedMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editedMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;morseText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;encodeToMorse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;composeExtension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;attachmentLayout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="c1"&gt;// The message UI component here&lt;/span&gt;
          &lt;span class="c1"&gt;// Please refer to the sample code on Glitch to see the entire code&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code sample shown in the &lt;strong&gt;bots.js&lt;/strong&gt;, I am using the simple UI "card" called &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference#adaptive-card/?WT.mc_id=m365-9173-timura" rel="noopener noreferrer"&gt;Thumbnail Card&lt;/a&gt; that comes with Bot Framework to compose the result message, but you can use Adaptive Card too!&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖💬 Trying your Message Action
&lt;/h3&gt;

&lt;p&gt;Now, let's try the action! Go to the Teams client, and click one of the text messages (not in rich format or image).&lt;/p&gt;

&lt;p&gt;If everything works as expected, you should be able to convert any text messages into a Morse code!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkvwq8o7fix7qowgeuoml.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkvwq8o7fix7qowgeuoml.gif" alt="Teams Message Action gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you get some good ideas about what you can do with Microsoft Teams platform with this tutorial, I hope you find better use cases than this and create something amazing! &lt;/p&gt;

&lt;p&gt;The next tutorial will walk you through how to build another type of Messaging Extension, which is a search command. See you next time 👋&lt;/p&gt;

</description>
      <category>node</category>
      <category>msteams</category>
      <category>m365</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Beginners Guide to MS Teams Development #2: Bots</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Mon, 05 Oct 2020 21:41:23 +0000</pubDate>
      <link>https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m</link>
      <guid>https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m</guid>
      <description>&lt;p&gt;Hello, I hope you enjoyed my &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k"&gt;previous tutorial&lt;/a&gt; on how to get started with Microsoft Teams development. &lt;/p&gt;

&lt;p&gt;This is the second one of the beginner series, and this time, I will walk you through how to build a conversational bot. &lt;/p&gt;

&lt;p&gt;There are many different paths to learn how to build Teams apps, and this tutorial uses a bare-minimum code and minimal toolsets. Also, this tutorial is independent of the hosting environment, so I am not staring the process with the Azure setup, and basically, this should run on any environment.  (Although this article is listed under MS Azure 😉)&lt;/p&gt;




&lt;p&gt;In &lt;a href="https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k"&gt;last article&lt;/a&gt;, I showed you how to embed a tab, but in this tutorial, I am going to show you a completely different feature, &lt;strong&gt;bots&lt;/strong&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Teams features: Bots
&lt;/h1&gt;

&lt;p&gt;There are &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/overview/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;a variety of features&lt;/a&gt; you can use to build Teams app, like Messaging extensions, tabs, etc. and bots turn words into actions, such as, generate an order, review my code, check ticket status, etc. A bot can kick off these kinds of workflows right inside Teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview-bots.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview-bots.png" alt="MS Teams bots"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you are going to do in this tutorial
&lt;/h2&gt;

&lt;p&gt;You are going to create a plain bot, which replies what you say in backward. Yes, this is not a useful bot at all, but hopefully, this sample gives some good ideas about what you'll build in the future.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure your app with App Studio&lt;/li&gt;
&lt;li&gt;Set up your code on an online IDE and run&lt;/li&gt;
&lt;li&gt;Use Microsoft Bot Framework to handle bot conversation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The end result would look like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffij31w2au7swf5gxwwom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffij31w2au7swf5gxwwom.png" alt="Teams bot"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  📓 Prerequisites
&lt;/h3&gt;

&lt;p&gt;To be able to install apps to Teams, your organization's admin needs to grant permission.&lt;/p&gt;

&lt;p&gt;Otherwise, you can sign up for &lt;strong&gt;Microsoft 365 developer program&lt;/strong&gt;, a free, renewable subscription that comes with a developer tenant sandbox and sample data pack, like mock user data!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permission to develop on Teams or developer tenant (&lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Sign up for M365 developer program!&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;App Studio - look for the app from the Apps menu in Teams client and install to your workspace&lt;/li&gt;
&lt;li&gt;Experience with Node.js and basic understanding of &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike the previous tutorial, that requires some front-end coding skills, to work with bots, you need a different skill set, and for this tutorial, Node.js.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building a chat bot
&lt;/h2&gt;
&lt;h3&gt;
  
  
  🎏 Grabbing the code sample
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I am using the 3rd party tool, &lt;a href="https://glitch.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Glitch&lt;/strong&gt;&lt;/a&gt; to host and run this project and the rest of the tutorial series. Glitch is a web-based IDE that you can write and run your node.js code, so at least for now, you can focus on learning the concepts and basics of Teams app development without worrying about running and tunneling localhost, or deploying. (I will cover them in the future!)&lt;/p&gt;

&lt;p&gt;First, let's just &lt;a href="https://glitch.com/edit/#!/remix/msteams-bot-minimum" rel="noopener noreferrer"&gt;click this Glitch link to &lt;em&gt;remix&lt;/em&gt; the project&lt;/a&gt;. Remixing is like the forking a repo on GitHub, so it generates a copy of the project for you, so you can modify the code in the way you want without messing with the original 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://glitch.com/edit/#!/remix/msteams-bot-minimum" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.glitch.com%2F2703baf2-b643-4da7-ab91-7ee2a2d00b5b%252Fremix-button.svg" alt="Remix on Glitch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get your own project repo, it serves up the app automatically and you get your own web server URL. For example, if your generated project name, usually it consists of a few random words, is achieved-diligent-bell, your Node server URL would be &lt;code&gt;https://achieved-diligent-bell.glitch.me&lt;/code&gt;. You can customize the name too if you want, too. You will need the URL when you are setting up an app with App Studio later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--AXHqSAT8--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4l4y51fnypv4h8tkggcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--AXHqSAT8--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4l4y51fnypv4h8tkggcn.png" alt="glitch project name"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ App Configuration: Creating App Manifest with App Studio
&lt;/h3&gt;

&lt;p&gt;This section is exactly the same as one in my previous tutorial to build tabs.&lt;/p&gt;

&lt;p&gt;When you are building any apps for Teams, you must create an app package to be installed to Teams client. The package includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 your-app-package
    └── 📄 manifest.json
    └── 🖼 color.png (192x192)
    └── 🖼 outline.png (32x32)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the rest of the app code and assets must be hosted on your webserver. (In this tutorial, we are using Glitch to automatically serve your app).&lt;/p&gt;

&lt;p&gt;We are not creating the manifest file manually today, but instead, we are going to create the app package using a visual tool called App Studio so you can create the package directly to Teams client.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎛 Using App Studio
&lt;/h3&gt;

&lt;p&gt;Installed &lt;strong&gt;App Studio&lt;/strong&gt; app in Teams client, if you haven't. Then, open the app. &lt;/p&gt;

&lt;p&gt;In App Studio, click the Manifest Editor tab from the top, then select &lt;strong&gt;Create a new app&lt;/strong&gt; and fill out all the required fields including the Bot names, descriptions, etc.&lt;/p&gt;

&lt;p&gt;At the App URLs section, fill out your privacy and Terms of Use webpage URLs. In this example, I am just using the placeholder URL, &lt;code&gt;https://example.com&lt;/code&gt;, but when you're developing apps to publish, you must have the web pages with the statements.&lt;/p&gt;

&lt;p&gt;Also, generate an App ID.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6v7c9sb6k5gpm4qot0ab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6v7c9sb6k5gpm4qot0ab.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔖 Configuring a bot
&lt;/h3&gt;

&lt;p&gt;From the left menu, select &lt;strong&gt;Capabilities &amp;gt; Bots&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Set up&lt;/strong&gt; to configure a new bot.&lt;/p&gt;

&lt;p&gt;Fill out the bot name, and let's just select the Personal scope for now. A personal bot allows conversing between bots and a single user. (To learn more about the scopes, read &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/conversation-basics/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Conversation basics&lt;/a&gt; on docs.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx8lnral7lc36qt9a9871.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx8lnral7lc36qt9a9871.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click &lt;strong&gt;Generate new password&lt;/strong&gt;. At the modal popup, copy the password, which you will need to paste it in your &lt;strong&gt;.env&lt;/strong&gt; file at the next step!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz90x87ldaf2ew0toqchj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz90x87ldaf2ew0toqchj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔐 App credentials
&lt;/h3&gt;

&lt;p&gt;Copy the ID next to your bot name (something looks like &lt;code&gt;2cd53e8a-e698-4exx-...&lt;/code&gt;) and paste it as an environment variable in your &lt;em&gt;.env&lt;/em&gt; file, which is supposed to be a hidden file (Rename the &lt;code&gt;.env-sample&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;App Passwords&lt;/strong&gt;, generate a new password, and copy it. Then paste it in your &lt;em&gt;.env&lt;/em&gt; file.&lt;/p&gt;

&lt;p&gt;These credentials are used to initialize your bot adapter. (See index.js).&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;Messagind Endpoint&lt;/strong&gt;, enter your bot server, which should be &lt;code&gt;https://[your project].glitch.me/api/messages&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 Installing the app manifest package
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Finish &amp;gt; Test and distribute&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you get any errors, go fix it, otherwise, click &lt;strong&gt;Install&lt;/strong&gt; your client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmtq6g1ul3n0tk3kof8rb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmtq6g1ul3n0tk3kof8rb.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also download the zip file that contains &lt;code&gt;manifest.json&lt;/code&gt;, and two icon images to install later or distribute.&lt;/p&gt;

&lt;p&gt;As long as you remixed the code sample, the bot should work already. But let me quickly explain how it is coded before trying the bot.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Microsoft Bot Framework
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.botframework.com/" rel="noopener noreferrer"&gt;Microsoft Bot Framework&lt;/a&gt; is an open source SDK that allows you to build intelligent, enterprise-grade bots. &lt;/p&gt;

&lt;p&gt;This SDK is a powerful platform that not only for Teams, but also designed to work for wide types of chat bots, including web &amp;amp; mobile chat, Skype, Facebook, Amazon Alexa, Slack, Twilio, and more!&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Initiating the bot service
&lt;/h3&gt;

&lt;p&gt;First, there are two JS files in the Glitch code sample repo, index.js and bots.js. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Glitch automatically pulls all dependencies from the pre-defined &lt;code&gt;package.json&lt;/code&gt; so you do not need to install the packages manually.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;index.js&lt;/strong&gt;, you need to include the libraries, &lt;a href="https://www.npmjs.com/package/botbuilder/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;botbuilder&lt;/a&gt;, and a library to set up an HTTP server and routing HTTP requests. I am using &lt;a href="https://www.npmjs.com/package/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; but you can use something else you prefer, such as, &lt;a href="https://www.npmjs.com/package/restify" rel="noopener noreferrer"&gt;Restify&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;index.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import Express &amp;amp; set up HTTP server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3978&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Import bot services&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BotFrameworkAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;botbuilder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Bot's main dialog&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReverseBot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: In this example, I am using botbuilder version 4.10.0. If your code doesn't work as expected, check the version you are using!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, set up the adapter that allows your bot to communicate with the user and send responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BotFrameworkAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MicrosoftAppId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MicrosoftAppPassword&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Error handlings (See the Glitch sample for details!)&lt;/span&gt;

&lt;span class="c1"&gt;// Create the main dialog&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myBot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ReverseBot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🦉 Forwarding requests to the bot logic
&lt;/h3&gt;

&lt;p&gt;Use Express to handle the routing to listen for incoming requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/messages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;processActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;myBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have set up the URL in App Studio in the previous step. The &lt;code&gt;/api/messages&lt;/code&gt; is your application’s endpoint URL to respond to client requests. &lt;/p&gt;

&lt;h3&gt;
  
  
  💬 Handling the request and post bot replies
&lt;/h3&gt;

&lt;p&gt;Once a request is received at the endpoint and forwarded to the bot logic, your app receive the context of the request, then create a custom reply in &lt;strong&gt;bots.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;See the &lt;code&gt;TeamsActivityHandler&lt;/code&gt; is extended to create an appropriate handler for the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TeamsActivityHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MessageFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;botbuilder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReverseBot&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TeamsActivityHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;backward&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// reverse string&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;replyText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`🙃 *&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;backward&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;*`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// you can use markdown&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MessageFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;replyText&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;TeamsActivityHandler&lt;/code&gt; is a Teams specific class that handles messages- such as messages events (&lt;em&gt;e.g.&lt;/em&gt; &lt;code&gt;onMembersAdded&lt;/code&gt; method is called whenever a member is added to the conversation), and sending replies.&lt;/p&gt;

&lt;p&gt;In the example, when a message is send to the client, the &lt;code&gt;onMessage&lt;/code&gt; is triggered, and you can grab the message text and use it to create the custom reply, in this case, reverse the string and send back to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖💬 Trying your bot
&lt;/h3&gt;

&lt;p&gt;Now, let's try the bot! Go to the Teams client, and click launch the bot from the left menu bar. &lt;/p&gt;

&lt;p&gt;If everything works as expected, you should be able to converse with the bot like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffij31w2au7swf5gxwwom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffij31w2au7swf5gxwwom.png" alt="Teams bot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This example only shows you how to send a text reply, however, you can create more interactive messages using buttons and other UI components. I will explain more about it later. &lt;/p&gt;

&lt;p&gt;I hope you enjoyed the tutorial, I hope you find better use cases than this and create something amazing! See you next time 👋&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MS Teams Documentation - &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/bots/what-are-bots/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;What are conversational bots?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.botframework.com/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Microsoft Bot Frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bot Services Documentation - &lt;a href="https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0&amp;amp;tabs=javascript&amp;amp;WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;How bot works?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Microsoft Azure tutorials &amp;amp; articles on &lt;a href="https://dev.to/azure"&gt;Dev.to&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>msteams</category>
      <category>m365</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Beginners Guide to MS Teams Development #1: Tabs</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Thu, 01 Oct 2020 21:47:32 +0000</pubDate>
      <link>https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k</link>
      <guid>https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k</guid>
      <description>&lt;p&gt;I hope you are all doing well while the pandemic is still at large. Well, since we all stay indoors most of the time, we can leverage the time to learn something new rather than hibernate 🐻💤  &lt;/p&gt;

&lt;p&gt;So this tutorial is my first of the beginner series for Microsoft Teams development. This is good for developers, who are using &lt;strong&gt;Microsoft Teams&lt;/strong&gt; at your work and thinking about building some apps (can be internal tools, or publish for everybody) that run inside of Teams, and/or who have published some app on other platforms like Slack and want to gain more users on Teams. Also, you don't need to have prior experience with any Microsoft cloud technology to try this tutorial!&lt;/p&gt;

&lt;p&gt;There are many different paths to learn how to build Teams apps, and this tutorial uses a bare-minimum code and minimal toolsets with some visual approach. Alternatively, try the tutorial on the &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/build-your-first-app/build-and-run/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Microsoft docs&lt;/a&gt;, if you want to jump ahead with the full-scale approach.&lt;/p&gt;




&lt;p&gt;Okay, as the very first of this beginner series, let me quickly explain what &lt;strong&gt;tabs&lt;/strong&gt; feature is. &lt;/p&gt;

&lt;h1&gt;
  
  
  Teams features: Tabs
&lt;/h1&gt;

&lt;p&gt;There are &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/overview/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;a variety of features&lt;/a&gt; you can use to build Teams app, like Messaging extensions, conversational bots, etc. and Tabs are where you can display any information in any visual interface. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview-tabs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fmicrosoftteams%2Fplatform%2Fassets%2Fimages%2Foverview-tabs.png" alt="MS Teams tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Technically, tabs are just &lt;em&gt;iframes&lt;/em&gt;, where you can display any webpages. You just have to configure to display it correctly on Teams!&lt;/p&gt;

&lt;p&gt;Here, I am going to show you how to create two types of Tabs - a &lt;strong&gt;personal tab&lt;/strong&gt; (only viewable by the person who installed it) and a &lt;strong&gt;team tab&lt;/strong&gt; (a team-level tab).&lt;/p&gt;

&lt;h2&gt;
  
  
  What you are going to do in this tutorial
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Configure your app with App Studio&lt;/li&gt;
&lt;li&gt;Build a personal tab on an online IDE and serve from there &lt;/li&gt;
&lt;li&gt;Re-configure to modify it to a channel/group tab&lt;/li&gt;
&lt;li&gt;Add more functions for the team tab&lt;/li&gt;
&lt;li&gt;Add the dark mode support&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The end result would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqppngw4qmrgv5pm080mb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqppngw4qmrgv5pm080mb.gif" alt="Team Tab GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📓 Prerequisites
&lt;/h3&gt;

&lt;p&gt;To be able to install apps to Teams, your organization's admin needs to grant permission. &lt;/p&gt;

&lt;p&gt;Otherwise, you can sign up for &lt;strong&gt;Microsoft 365 developer program&lt;/strong&gt;, a free, renewable subscription that comes with a developer tenant sandbox and sample data pack, like mock user data!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permission to develop on Teams &lt;em&gt;or&lt;/em&gt; developer tenant (&lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Sign up for M365 developer program!&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;App Studio - look for the app from the Apps menu in Teams client and install to your workspace&lt;/li&gt;
&lt;li&gt;Basic knowledge of JavaScript&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Building a Personal Tab
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎏 Grabbing the code sample
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I am using the 3rd party tool, &lt;a href="https://glitch.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Glitch&lt;/strong&gt;&lt;/a&gt; to host and run this project and the rest of the tutorial series. Glitch is a web-based IDE that you can write and run your node.js code, so at least for now, you can focus on learning the concepts and basics of Teams app development without worrying about running and tunneling localhost, or deploying. (I will cover them in the future!)&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://glitch.com/~msteams-tab-minimum" rel="noopener noreferrer"&gt;the sample code&lt;/a&gt; page and &lt;em&gt;remix&lt;/em&gt; the project. Remixing is like  the forking a repo on GitHub, so it generates a copy of the project for you, so you can modify the code in the way you want without messing with the original 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkiqsgijoodq3wcyl94mm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkiqsgijoodq3wcyl94mm.png" alt="remix on glitch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get your own project repo, it serves up the app automatically and you get your own web server URL. For example, if your generated project name, usually it consists of a few random words, is &lt;em&gt;achieved-diligent-bell&lt;/em&gt;, your webserver URL would be &lt;code&gt;https://achieved-diligent-bell.glitch.me&lt;/code&gt;. You can customize the name too if you want, too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4l4y51fnypv4h8tkggcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4l4y51fnypv4h8tkggcn.png" alt="Glitch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ App Configuration: Creating App Manifest with App Studio
&lt;/h3&gt;

&lt;p&gt;When you are building apps for Teams, you must create an app package to be installed to Teams client. The package includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 your-app-package
    └── 📄 manifest.json
    └── 🖼 color.png (192x192)
    └── 🖼 outline.png (32x32)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the rest of the app code and assets must be hosted on your webserver. (In this tutorial, we are using Glitch to automatically serve your app).&lt;/p&gt;

&lt;p&gt;We are not creating the manifest file manually today, but instead, we are going to create the app package using a visual tool called &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/app-studio-overview/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;App Studio&lt;/a&gt; so you can create the package directly to Teams client.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎛 Using App Studio
&lt;/h3&gt;

&lt;p&gt;Once you have installed &lt;strong&gt;App Studio&lt;/strong&gt; app in Teams client, open the app. You can launch it by clicking the &lt;strong&gt;. . .&lt;/strong&gt; from the left menu bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffabomd9xhvydr2qu49i4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffabomd9xhvydr2qu49i4.png" alt="Open App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click the &lt;strong&gt;Manifest Editor&lt;/strong&gt; tab from the top, then select &lt;strong&gt;Create a new app&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl1lmbvzep51he038lrjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl1lmbvzep51he038lrjg.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are going to need to fill out all the required fields including the app names, descriptions, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxdgv7b3r3bfpord8y2u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxdgv7b3r3bfpord8y2u1.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the &lt;strong&gt;App URLs&lt;/strong&gt; section, fill out your privacy and TOU webpages. In this example, I am just using the placeholder URL, &lt;code&gt;https://example.com&lt;/code&gt;, but when you're developing apps to publish, you must have the web pages with the statements.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔖 Configuring a personal tab
&lt;/h3&gt;

&lt;p&gt;From the left menu, select &lt;strong&gt;Capabilities&lt;/strong&gt; &amp;gt; &lt;strong&gt;Tabs&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8rvvye4e8kpjsddfq1q1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8rvvye4e8kpjsddfq1q1.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Add&lt;/strong&gt; button under &lt;strong&gt;Add a personal tab&lt;/strong&gt; and enter the info. &lt;br&gt;
Under &lt;strong&gt;Content URL&lt;/strong&gt;, enter your webpage URL (should be &lt;code&gt;https://[your-project-name].glitch.me/index.html&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft6sobwvc6fga3ro1kt0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft6sobwvc6fga3ro1kt0r.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, the &lt;strong&gt;index.html&lt;/strong&gt; file has nothing more than a few lines of static HTML code (and some CSS):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello world! &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is the bare-minimum setting for MS Teams Tabs. &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to tweak the content in the &lt;strong&gt;index.html&lt;/strong&gt; as you want. This is the content to be displayed in your Teams client.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎉 Finish creating the app manifest package
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Finish&lt;/strong&gt; &amp;gt; &lt;strong&gt;Test and distribute&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftodl0aot8ahkphtdbcnh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftodl0aot8ahkphtdbcnh.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you get any errors, go fix it, otherwise, click &lt;strong&gt;Install&lt;/strong&gt; your client. &lt;/p&gt;

&lt;p&gt;Ta-da, now you have the personal tab at the left menu 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnl847l1axkg04z1zwb9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnl847l1axkg04z1zwb9j.png" alt="Personal tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If something is wrong after installing it properly, check if the Content URL is set correctly. Make sure that you're using your own web server URL, like &lt;code&gt;https://[your-project-name].glitch.me/index.html&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You can stop here, or proceed to make it into a team tab at the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Building a Channel/Group Tab
&lt;/h2&gt;

&lt;p&gt;Now, let's transform this into a channel/group tab. It requires a few extra steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎏 Grabbing the code sample on Glitch
&lt;/h3&gt;

&lt;p&gt;You can directly remix the code sample by clicking the &lt;a href="https://glitch.com/edit/#!/msteams-teamtab-minimum?path=README.md%3A1%3A0" rel="noopener noreferrer"&gt;remix link here&lt;/a&gt; this time. Or feel free to continue with the previous code sample and modify the code.&lt;/p&gt;

&lt;p&gt;Notice that this code sample has the additional &lt;strong&gt;config.html&lt;/strong&gt;, also some JavaScript code added. &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Tweaking App Configuration
&lt;/h3&gt;

&lt;p&gt;Go back to &lt;strong&gt;App Studio&lt;/strong&gt;, open the app you just create, and let's modify the tabs settings. (Or create a new app if you want a fresh one! In this case, you will need to fill out the app details for the new app.)&lt;/p&gt;

&lt;h3&gt;
  
  
  🔖 Configuring a team tab
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Capabilities&lt;/strong&gt; &amp;gt; &lt;strong&gt;Tabs&lt;/strong&gt;. You can either leave or delete the personal tab you have created previously.&lt;/p&gt;

&lt;p&gt;Click the "Add" button under &lt;strong&gt;Team tab&lt;/strong&gt;, and enter the info. &lt;br&gt;
Under &lt;strong&gt;Configuration URL&lt;/strong&gt;, enter your web URL (should be &lt;code&gt;https://[your-project-name].glitch.me/config.html&lt;/code&gt;). Even if you don't have any configurable content, this field is required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F757021f4iby78i4ba88m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F757021f4iby78i4ba88m.png" alt="App Studio"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Using JavaScript SDK for Tabs to load the content
&lt;/h3&gt;

&lt;p&gt;Unlike the personal tab, which can be just a plain static HTML, for the team tab, let's use the &lt;a href="https://docs.microsoft.com/en-us/javascript/api/@microsoft/teams-js/?view=msteams-client-js-latest&amp;amp;WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;SDK&lt;/a&gt; to load the main content.&lt;/p&gt;

&lt;p&gt;Notice that these lines of code are included in the &lt;strong&gt;config.html&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: As you may notice, this example uses SDK version 1.6.0. If your code doesn't work as expected, check the version you are using!&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microsoftTeams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;microsoftTeams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSettings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;contentUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://msteams-teamtab-minimum.glitch.me/index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;microsoftTeams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValidityState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add some dynamic values like some user locale info by using the &lt;code&gt;getContext()&lt;/code&gt; method. To learn more about the Teams SDK, read the &lt;a href="https://docs.microsoft.com/en-us/javascript/api/overview/msteams-client?view=msteams-client-js-latest&amp;amp;WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;SDK documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, try the app by going to &lt;strong&gt;Finish&lt;/strong&gt; &amp;gt; &lt;strong&gt;Test and distribute&lt;/strong&gt; and install the app.&lt;/p&gt;

&lt;p&gt;If everything goes well, your app appears at the top of the client 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqppngw4qmrgv5pm080mb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqppngw4qmrgv5pm080mb.gif" alt="Team Tab GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔦 Theming (Supporting Dark Mode &amp;amp; High-Contrast Mode)
&lt;/h3&gt;

&lt;p&gt;But wait, what if you and your potential app users are in the dark mode? Does it automatically handle the color change in the iframe?&lt;/p&gt;

&lt;p&gt;No. So let's fix that.&lt;/p&gt;

&lt;p&gt;Take a look at one of the view HTML files. Notice it has JavaScript to handle the theme detection (and theme change event handling). &lt;/p&gt;

&lt;p&gt;In this example, on the default (light) theme, the default text color (typically black) is used, otherwise, white.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microsoftTeams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;microsoftTeams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerOnThemeChangeHandler&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inherit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's toggle the theme and see how the change is reflected. &lt;/p&gt;

&lt;p&gt;You can change the client theme color by going to the settings menu from your avatar at the top-right.&lt;/p&gt;

&lt;p&gt;The font color should be white in the dark or high-contrast mode like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqkuserid8seqegpqnit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqkuserid8seqegpqnit.png" alt="Teams dark mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🙌 &lt;/p&gt;

&lt;p&gt;I hope you have better ideas on how you can get started with Microsoft Teams app development.&lt;/p&gt;




&lt;p&gt;In the tutorial, to make as simple as possible, I did not tell you how to use the recommended toolsets, however, in the reality, you probably create a full-fledged app with more tools with VS Code and probably some front-end framework like React with a build manager, etc, and deploy to Azure! Stay tuned for these tutorials too.&lt;/p&gt;

&lt;p&gt;To learn more, please go check the links below. &lt;/p&gt;

&lt;p&gt;In the next tutorials, I will show you how to create interactive message extensions. So, see you next time 👋 &lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/overview/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;MS Teams Documentation&lt;/a&gt; - Overview &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/build-your-first-app/build-and-run/?WT.mc_id=m365-devto-timura" rel="noopener noreferrer"&gt;Build a Hello World App&lt;/a&gt; - this instruction uses VSCode, ngrok, and React.js&lt;/li&gt;
&lt;li&gt;Microsoft Azure tutorials &amp;amp; articles on &lt;a href="https://dev.to/azure"&gt;Dev.to&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>msteams</category>
      <category>m365</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Spread Syntax "Three-dots" Tricks You Can Use Now</title>
      <dc:creator>Tomomi Imura 🐱 </dc:creator>
      <pubDate>Thu, 18 Jun 2020 01:51:40 +0000</pubDate>
      <link>https://dev.to/girlie_mac/spread-syntax-three-dots-tricks-you-can-use-now-aob</link>
      <guid>https://dev.to/girlie_mac/spread-syntax-three-dots-tricks-you-can-use-now-aob</guid>
      <description>&lt;p&gt;&lt;em&gt;This articles is created based on my own &lt;a href="https://twitter.com/girlie_mac/status/1263955788990566400"&gt;tweet&lt;/a&gt; posted on May 22, 2020&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;ES6 (ECMAScript 2015, the 6th edition) was finalized 5 years ago, and brought us a significant amount of new syntax and features to help you write complex code better and simpler. &lt;/p&gt;

&lt;p&gt;I am assuming that many of you have consumed more calories from the syntactic sugar by adopting new features like class declarations, &lt;code&gt;let&lt;/code&gt; / &lt;code&gt;const&lt;/code&gt;, and arrow function expression, and so on, but how about some of the lesser-known &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;Spread operator&lt;/a&gt;? &lt;/p&gt;

&lt;p&gt;Here, I would like to share some good usages of spread operator, a.k.a three-dots that I've found while I was coding (and StackOverflowing, I don't lie about how I code!). &lt;/p&gt;

&lt;h2&gt;
  
  
  What do Three Dots do?
&lt;/h2&gt;

&lt;p&gt;First, there are two "three-dots" sugars introduced in ES6. One is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters"&gt;&lt;strong&gt;Rest parameter&lt;/strong&gt;&lt;/a&gt;, which allows us to use an arbitrary number of arguments, and another is &lt;strong&gt;Spread operator&lt;/strong&gt;, which also has the similar syntax with three dots, but it is more like the reversed version- it takes the array itself, not arguments. &lt;/p&gt;

&lt;p&gt;In this article, I am showing tricks that uses spread syntax. Looking at the practical examples may be far easier to understand what it does than by reading the definitions!&lt;/p&gt;




&lt;h2&gt;
  
  
  Concat
&lt;/h2&gt;

&lt;p&gt;You say "cat" so I say meow. &lt;/p&gt;

&lt;p&gt;Let's concatenate two arrays. Here we have two arrays that represent cat fur coat colors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;solid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bicolor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tabby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calico&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tortoiseshell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we traditionally did before ES6 using &lt;code&gt;concat()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ['solid', 'bicolor', 'tabby', 'calico', 'tortoiseshell']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can simply write with the ES6 spread syntax like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 
&lt;span class="c1"&gt;// ['solid', 'bicolor', 'tabby', 'calico', 'tortoiseshell']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Convert a string to array
&lt;/h2&gt;

&lt;p&gt;Have you been asked to reverse a string, or check if a string is a palindrome at job interviews? The questions you got may be more complex, but these are pretty common interview questions for software engineers. &lt;/p&gt;

&lt;p&gt;Anyway, the first step to solve the question is likely to convert the given string to an array.&lt;/p&gt;

&lt;p&gt;You have a given string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kitty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With pre-ES6 JavaScript, use &lt;code&gt;split()&lt;/code&gt; to get each letter in an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['k', 'i', 't', 't', 'y'];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with the ES6 spread syntax, you can achieve the same as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ['k', 'i', 't', 't', 'y'];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Find Max or Min
&lt;/h2&gt;

&lt;p&gt;Let's say, you have a given set of numbers,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find the largest (or smallest) number from the set of numbers, you can use &lt;code&gt;Math.max()&lt;/code&gt; (or &lt;code&gt;Math.min()&lt;/code&gt;) and pass the given numbers as input parameters like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with the ES6 spread syntax, you can pass an array of numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Copy an Array
&lt;/h2&gt;

&lt;p&gt;You can also create a shallow copy of an array with the spread syntax.&lt;/p&gt;

&lt;p&gt;You have an array,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allCatNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chewie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;leia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yoda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chewie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;luke&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;leia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And onne way to get a shallow copy of the array with the pre-ES6 is using &lt;code&gt;slice()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;allCatNamesCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allCatNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with ES6 spread syntax, you can simply do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allCatNamesCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;allCatNames&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Remove Dups from an Array
&lt;/h2&gt;

&lt;p&gt;The array, &lt;code&gt;allCatNames&lt;/code&gt; above has some duplicated values (&lt;code&gt;chewie&lt;/code&gt; and &lt;code&gt;leia&lt;/code&gt; appeared twice in the list). If want to remove the duplicates, you'll write multiple lines of code with pre-ES6 JavaScript- &lt;/p&gt;

&lt;p&gt;You probably would iterate the array. And at each loop, map each value in an object to track if the key in the object is unique, and if yes, the value is pushed to a new array. Then at the end of the loop, you have the new array only with unique values.&lt;/p&gt;

&lt;p&gt;You can actually achieve this in one line of code with spread syntax by creating a new array with combination of the spread syntax with the &lt;code&gt;Set&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;catNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allCatNames&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt; 
&lt;span class="c1"&gt;// ['chewie', 'leia', 'yoda', 'luke'];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ta-da, this saves a lot of code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Collecting HTML Elements in an Array
&lt;/h2&gt;

&lt;p&gt;If you are a front-end JavaScript developer, this trick may be useful when you manipulate DOM-&lt;/p&gt;

&lt;p&gt;Let's say, when you re trying to grab every element with the class name, &lt;code&gt;.cat&lt;/code&gt;, you probably use &lt;code&gt;querySelectorAll()&lt;/code&gt; to get the collection of the DOM nodes.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;document.querySelectorAll('.cat')&lt;/code&gt; returns a static &lt;em&gt;NodeList&lt;/em&gt;, which is an array-like, but not exactly an array that you can iterate over it.&lt;/p&gt;

&lt;p&gt;So in some occasions, you need to convert a NodeList to Array. Traditionally, you probably have been writing code like this, which doesn't seem so intuitive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;catElementArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[].&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with the spread syntax, you can rewrite as followings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;catElementArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks more intuitive, doesn't it?&lt;/p&gt;




&lt;p&gt;Well, if you like the three-dots notation or not, now you see that the spread operator can be quite handy when you work with arrays and objects.&lt;/p&gt;

&lt;p&gt;I would be happy if I just convinced you to use the three-dots in your daily code from now on. Surely, there are more clever ways to write code with using the spread operator, so if you know the tricks, please share with me and the rest of the JS community!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wants to find out more about ES.Next?
&lt;/h3&gt;

&lt;p&gt;I will be giving a talk, &lt;em&gt;ECMeowScript - What’s new in JavaScript Explained with Cats&lt;/em&gt; at &lt;a href="https://forwardjs.com/"&gt;Forward JS&lt;/a&gt; (&lt;del&gt;San Francisco&lt;/del&gt; virtual) and &lt;a href="https://webdirections.org/"&gt;Web Directions&lt;/a&gt; (&lt;del&gt;Sydney&lt;/del&gt; virtual) in September, so I hope you can catch my talk! 🐱&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Edit: Conference month has been updated.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ciao!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>es6</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
