<?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: Mike Homol</title>
    <description>The latest articles on DEV Community by Mike Homol (@mhomol).</description>
    <link>https://dev.to/mhomol</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%2F353697%2F329ad8db-1081-469a-aa50-a0f9733eeea5.jpeg</url>
      <title>DEV Community: Mike Homol</title>
      <link>https://dev.to/mhomol</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhomol"/>
    <language>en</language>
    <item>
      <title>How to make a modal window on a PowerApp screen</title>
      <dc:creator>Mike Homol</dc:creator>
      <pubDate>Thu, 21 Jan 2021 17:05:04 +0000</pubDate>
      <link>https://dev.to/mhomol/how-to-make-a-modal-window-on-a-powerapp-screen-b5j</link>
      <guid>https://dev.to/mhomol/how-to-make-a-modal-window-on-a-powerapp-screen-b5j</guid>
      <description>&lt;p&gt;This is a cross-post from &lt;a href="https://homol.work/blog/powerappmodal20201223"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modal windows and pop-ups are a staple of applications. Ever just needed to quickly make one in your PowerApp?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is a quick and easy step-by-step for making a pop-up modal window on a screen in your PowerApp.&lt;/p&gt;

&lt;p&gt;Let's assume we have an app screen that's collecting some survey data. Like so:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--By7Vnks9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/start-screen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--By7Vnks9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/start-screen.png" alt="Start Screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It would be nice if we could provide a little more information to explain the Account Number that is needed.&lt;/p&gt;

&lt;p&gt;Insert a new Icon onto the screen and give it the Information image.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YHMOhzrh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/info-icon.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YHMOhzrh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/info-icon.gif" alt="Information Icon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your screen and add the following to the OnVisible event:&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;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ShowModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ModalText&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, select your new information icon and add the following to the OnSelect event:&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;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;ModalText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your account number is located at the top right of your most recent bill.&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;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ShowModal&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;Insert a label onto the screen and adjust it's width and height to cover the entire screen. Name this label &lt;code&gt;ModalBackground&lt;/code&gt; and remove it's Text.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R5954JKz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/modal-background.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R5954JKz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/modal-background.gif" alt="Modal Background Label"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, set the Fill property of this background label to &lt;code&gt;RGBA(169,169,169,.5)&lt;/code&gt;. It should look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5qJQ0I1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-bg-gray.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5qJQ0I1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-bg-gray.png" alt="Gray Modal Background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a second label and name it &lt;code&gt;ModalBox&lt;/code&gt;. Center it's horizontal alignment and make the vertical alignment in the middle. Additionally, give it a Fill of White, center align its text and give it some extra padding. It should look something like this when you're done.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hsdn_HtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-box-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hsdn_HtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-box-1.png" alt="Modal Textbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the Text property of the 'ModalBox' label to &lt;code&gt;ModalText&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add a Cancel Icon to the screen and place it in the top right corner of the &lt;code&gt;ModalBox&lt;/code&gt; label. Name it &lt;code&gt;ModalClose&lt;/code&gt;. Now you should have something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2rMCrhTB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-box-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2rMCrhTB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-box-2.png" alt="Modal Textbox with Close"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Put the following code in the OnSelect event of &lt;code&gt;ModalClose&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="nx"&gt;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ShowModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;UpdateContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ModalText&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Group the 3 new controls you have added and name the group &lt;code&gt;Modal&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L3H9eiUV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-group.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L3H9eiUV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/modal/modal-group.png" alt="Modal Group"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the Visible property of the &lt;code&gt;Modal&lt;/code&gt; group to &lt;code&gt;ShowModal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you've done everything, you're modal should look and work like so:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kkI4ExVQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/modal-in-action.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kkI4ExVQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/modal/modal-in-action.gif" alt="Modal in Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a quick and painless process to have modals at your disposal in your next PowerApp. Happy low-coding!&lt;/p&gt;

</description>
      <category>powerplatform</category>
      <category>m365</category>
      <category>tipsandtricks</category>
    </item>
    <item>
      <title>All of the Things! Custom MS Search Vertical of Serverless Azure DB and the new SQL Graph Connector!</title>
      <dc:creator>Mike Homol</dc:creator>
      <pubDate>Sun, 05 Jul 2020 15:46:48 +0000</pubDate>
      <link>https://dev.to/mhomol/all-of-the-things-custom-ms-search-vertical-of-serverless-azure-db-and-the-new-sql-graph-connector-1b30</link>
      <guid>https://dev.to/mhomol/all-of-the-things-custom-ms-search-vertical-of-serverless-azure-db-and-the-new-sql-graph-connector-1b30</guid>
      <description>&lt;p&gt;Cross-post from &lt;a href="https://homol.work/blog/customvertserverlesssql20200703"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/microsoftsearch/connectors-overview"&gt;Microsoft Graph Connectors&lt;/a&gt; are now in preview mode and appear to be showing up for most folks who have turned on targeted releases in their Dev tenants. So, naturally, I had to see what we could break... er, do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Just how much can we throw in here?
&lt;/h2&gt;

&lt;p&gt;Just to spice things up for this blog post, let's see if we can pull in as many different and new-ish things into this bad boy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ozqSSRBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/4754vw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ozqSSRBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/4754vw.jpg" alt="Throw it all in!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL or bust
&lt;/h2&gt;

&lt;p&gt;One of the first things I wanted to try out was the &lt;a href="https://docs.microsoft.com/en-us/microsoftsearch/mssql-connector"&gt;SQL Server connector&lt;/a&gt;. This is big win for SharePoint and 365 to be able to include 3rd-party structured data without any custom development. So it felt like a great candidate to try out first. So here was problem 1: I had no "on-prem" SQL database anymore. And SQL is expensive. Or is it? &lt;a href="https://peteskelly.com"&gt;Pete Skelly&lt;/a&gt; turned my eyes towards &lt;a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/serverless-tier-overview#:~:text=Azure%20SQL%20Database%20serverless%201%20Serverless%20compute%20tier.,...%2010%20Resource%20limits.%20...%20More%20items...%20"&gt;serverless Azure SQL&lt;/a&gt; - a consumption-based model for SQL. Seems pretty new and cool to me. Let's throw it in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotta have a VM
&lt;/h2&gt;

&lt;p&gt;We want to mimic an "on-prem" experience, so that means trying to use the &lt;a href="https://powerbi.microsoft.com/en-us/gateway/"&gt;Power BI gateway&lt;/a&gt; to connect to our SQL database. So let's make sure we have a VM to install the gateway onto that will sign in with a dev tenant login and can then connect to the SQL server. Things are looking good. Anything else?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kEax7mOJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475j8q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kEax7mOJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475j8q.jpg" alt="Bump up those numbers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some automation, perhaps?
&lt;/h2&gt;

&lt;p&gt;What if we see how much of this we can build with ARM templates? Yeah, that sounds good. &lt;a href="https://marketplace.visualstudio.com/items?itemName=msazurermtools.azurerm-vscode-tools"&gt;The ARM Tools extension&lt;/a&gt; for VSCode is pretty solid. Channel 9's DevOpsLab just started a video series on &lt;a href="https://channel9.msdn.com/Shows/DevOps-Lab/Demystifying-ARM-Templates-Creating-Your-First-Template"&gt;Demystifying ARM Templates&lt;/a&gt;, which shows the power of the MS team's JSON schema they've built. So yeah, why not throw that in. Plus, I've been wanting an opportunity to use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bencoleman.armview"&gt;ARM Template Viewer&lt;/a&gt; extension in VSCode too, so now I have a reason and a way to visually represent almost everything we're creating for this little Graph Connector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, what are we doing again?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DJnk0yps--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475ioo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DJnk0yps--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475ioo.jpg" alt="All part of the plan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So here's the plan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serverless Azure SQL database as a backend&lt;/li&gt;
&lt;li&gt;The AdventureWorks database loaded up with Product data&lt;/li&gt;
&lt;li&gt;Windows VM with a Power BI gateway to connect to the Azure SQL db&lt;/li&gt;
&lt;li&gt;A new graph connector, which uses the gateway to crawl Products, to display in a new vertical in MS Search results&lt;/li&gt;
&lt;li&gt;A custom adaptive card display (&lt;em&gt;we gotta see if we can pipe in product pictures, right?&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a high-level overview of the data flow, from SQL-to-VM-to-365:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mjDOHcbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/High-Level-Data-Flow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mjDOHcbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/High-Level-Data-Flow.png" alt="High-Level Data Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The VM's gateway will be controlled by the 365 Search service and graph connector API. Every 15 minutes, 365 will attempt an incremental crawl, by reaching out to the gateway on the VM, which will receive a query to execute agains the SQL DB on Azure. So let's get this party started.&lt;/p&gt;
&lt;h2&gt;
  
  
  ARMing ourselves (get it?)
&lt;/h2&gt;

&lt;p&gt;Based on the above, here's what our ARM template needs to look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ersWUs0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/full_simple.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ersWUs0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/full_simple.png" alt="ARM Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This diagram made possible by &lt;a href="https://marketplace.visualstudio.com/items?itemName=bencoleman.armview"&gt;ARM Template Viewer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don't feel like making all of this? No problem! I've already set it all up and exported it to an ARM Template for you! I even went ahead and took the time to set it up a little better for automation. I've provided 2 files for you to use to get all of this provisioned automagically in your own tenant/subscription:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/mhomol/Experiments/blob/master/On-Prem%20SQL%20Graph%20Connector/ARM%20Templates/full_simple.json"&gt;full_simple.json&lt;/a&gt; - this is the ARM template that represents the above design&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mhomol/Experiments/blob/master/On-Prem%20SQL%20Graph%20Connector/ARM%20Templates/runit.azcli"&gt;runit.azcli&lt;/a&gt; - this is an Azure CLI script that is built for Bash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply put the 2 files next to each other from wherever you plan on running them. If you want to run it from the cloud shell, like I did, you'll just have to upload them first, like so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EiQ4WKOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-upload-arm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EiQ4WKOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-upload-arm.png" alt="Optional: upload the files to Cloud Shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ARM Template JSON has a number of preset variables you should know about. If you want it to run successfully, you'll need to set them to be something unique for you. These variables are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rg&lt;/code&gt; - A reprint of the resource group you plan on putting everything in. That will also get set in the &lt;em&gt;runit.azcli&lt;/em&gt;. This name just gets used in some of the more generic naming of things like the NICs and NSGs that I'm hoping you don't have to even think about.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vmname&lt;/code&gt; - The name of the VM that will get made for you&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;location&lt;/code&gt; - This also gets set in &lt;em&gt;runit.azcli&lt;/em&gt; so you don't necessarily have to set it here.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;servers_serverlessserverpoc_name&lt;/code&gt; - The name of the database server that will be created&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;adventureworks_dbname&lt;/code&gt; - The name of the database (defaults to HomolWorks)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;uniquedomainprefix&lt;/code&gt; - Should probably be the same as the name you pick for the VM - using this will make RDP'ing easier&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;my_ip&lt;/code&gt; - if you set this, then your IP will be automatically added to the firewall rules for the Database server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sqladmin_account&lt;/code&gt; - the SQL admin user name. Defaults to POCAdmin&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vmadmin_name&lt;/code&gt; - the VM admin user name. Defaults to captainawesome&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Run it!
&lt;/h3&gt;

&lt;p&gt;The script only has 3 variables it tries to preset before deploying the ARM template. Naturally you could edit this all you want and feed in more parameters rather than setting them up in the .json file. Only 2 variables really need to be set: &lt;code&gt;rg&lt;/code&gt; and &lt;code&gt;location&lt;/code&gt;. This ARM template is scoped to a resource group, so the script creates that Resource Group first, then deploys the ARM template to the group. Note that you can optionally set the IP you're developing from in the &lt;code&gt;my_ip&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Once you've set &lt;code&gt;rg&lt;/code&gt; and &lt;code&gt;location&lt;/code&gt;, run the &lt;em&gt;runit.azcli&lt;/em&gt; script from a terminal using Bash or Zsh. I ran mine from Azure Cloud Shell.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J6ivjF5---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-run-azcli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J6ivjF5---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-run-azcli.png" alt="Running the Script"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not so bad so far, right? If you're feeling really adventurous, be sure to look over the ARM Template in full to see everything we've got going on. Lots of small stuff has been squirreled away so you don't have to care.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;NOTE that I did actually get an error running the template, which was during the setup of one of the advisors for the SQL database, where I was told the resources were busy. But everything had actually executed fine, at least for the purposes of this Proof-of-Concept. So if you get that error, just make sure that the AdventureWorks database was provisioned in the new resource group and you should be good to go.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, we're ARMed. What do we have to show for it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KLKrWeXe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475mr2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KLKrWeXe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgflip.com/475mr2.jpg" alt="Tis but a scratch"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Review and Connect
&lt;/h2&gt;

&lt;p&gt;Let's review everything we have now that the script and ARM template have finished. First let's just take a look at the finished Resource Group. Quite a few resources have been generated and most of them will cost next to nothing. And here's the best part: you can just delete the resource group whenever and be done with this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kmQBEomn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kmQBEomn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-rg.png" alt="Our new resource group"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the VM and notice the top right portion of the Overview tab. We have a static IP and a DNS. This will make for easy RDP, plus it has been beneficial to setting up our DB firewall.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S0-WIb80--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-vm-ip-dns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S0-WIb80--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-vm-ip-dns.png" alt="VM IP and DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see where that IP is used by SQL. Go back to the resource group and click on the SQL server. Then select the Firewalls and Virtual Networks option. Note in the IP Address rules that we already have an item added - the same IP as our VM. If you hadn't setup your IP, now could be a good time to add that a Save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8zG6Bokp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-db-firewall.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8zG6Bokp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-db-firewall.png" alt="SQL server firewall"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Gateway Time
&lt;/h3&gt;

&lt;p&gt;Remember that DNS? Well now's our chance to use it. Connect with your favorite RDP client, using the domain that was created and the VM admin account/password that you setup in the ARM template parameters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TeG4Cn2T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-rdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TeG4Cn2T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-rdp.png" alt="RDP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to install the gateway. To start go to &lt;a href="https://powerbi.microsoft.com/en-us/gateway/"&gt;https://powerbi.microsoft.com/en-us/gateway/&lt;/a&gt; and select &lt;em&gt;Download Standard Mode&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2cYrYgQv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-standard-install.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2cYrYgQv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-standard-install.png" alt="Gateway Install"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it's installed, sign in using your dev tenant admin account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YkMenKHK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-dev-tenant-login.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YkMenKHK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-dev-tenant-login.png" alt="Gateway Signin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;em&gt;Register a new gateway on this computer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XCYhTI5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-new.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XCYhTI5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-new.png" alt="New Gateway"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, setup a name for the gateway and a recovery key (which is a passphrase of your choosing).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4kHOszzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-name-key.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4kHOszzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-gw-name-key.png" alt="Gateway name and key"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Graph connector setup
&lt;/h2&gt;

&lt;p&gt;Okay, we're almost there. Time to setup our &lt;a href="https://docs.microsoft.com/en-us/microsoftsearch/mssql-connector"&gt;sql graph connector&lt;/a&gt;. First, let's confirm that you can even do this. As we mentioned earlier, this is still in preview mode at the time of this writing, so if you want to have a shot at seeing the connectors, you need to set you organization settings to getting targeted releases. See the animation below for accessing that setting from the 365 admin center:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oy4c_sGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/TargetedReleaseSetting.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oy4c_sGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/TargetedReleaseSetting.gif" alt="Targeted Release Setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's where you go to access connectors. In the 365 admin center, select Settings-&amp;gt;Microsoft Search and confirm that you have the Connectors tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xdQ5OPzE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/SQLServerConnectorStart.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xdQ5OPzE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/SQLServerConnectorStart.gif" alt="Connectors tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To connect to our SQL Server, click Add, then Microsoft SQL Server. Then supply a Name, a Connection ID (just a unique identifier of your choosing) and a description. Finally accept the terms to proceed.&lt;/p&gt;

&lt;p&gt;After we click Next, it's time for us to setup our database connection. &lt;em&gt;Finally!&lt;/em&gt; To get your connection string, head back over to Azure and select your database. Then select the Connection Strings option along the left. The first tab holds the information you'll need over in your 365 dev tenant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zut5f7TE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-connstring.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zut5f7TE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/step-connstring.png" alt="DB Connection String"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that in the Database Settings step for the graph connector, the On-premises gateway is selectable. You should see the name you provided for your gateway in there. Select it. Fill out the parts need for the connection and click Test Connection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zFblW7Ca--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ConnectToHomolWorks.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zFblW7Ca--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ConnectToHomolWorks.gif" alt="Test the connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's happening under the hood is that 365 is reaching out to the gateway agent running on your VM and &lt;em&gt;then&lt;/em&gt; making the connection to the database, which has allowed your VM to connect through it's Firewall rules. Pretty neat, huh?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jd6GLB0N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fmedia.tenor.com%252Fimages%252F31245191ed807ecd9be31aeaeae6a626%252Ftenor.gif%26f%3D1%26nofb%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jd6GLB0N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fmedia.tenor.com%252Fimages%252F31245191ed807ecd9be31aeaeae6a626%252Ftenor.gif%26f%3D1%26nofb%3D1" alt="Aw yeah"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What exactly is in this AdventureWorks, anyway?
&lt;/h3&gt;

&lt;p&gt;Okay, so the last few steps of the Graph Connector are about setting up the data to be crawled. So what exactly do we have here? We're going to focus on Products. Here's a quick snapshot of the tables though from the &lt;a href="https://docs.microsoft.com/en-us/sql/azure-data-studio/download-azure-data-studio?view=sql-server-ver15"&gt;Azure Data Studio&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qpVKkM_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/AdventureWorks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qpVKkM_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/AdventureWorks.png" alt="AdventureWorks Product data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We intend to target Product and we will also include the Product Model through a join.&lt;/p&gt;

&lt;p&gt;The next step in the Graph Connector setup is to provide our full crawl query. &lt;em&gt;Note&lt;/em&gt; that we are expected to provide a date field that we will base the query off of, so that only items added after the previous crawl will be pulled to make things more efficient. This is the watermark field (&lt;code&gt;@watermark&lt;/code&gt;). We have chosen &lt;code&gt;CreateDate&lt;/code&gt; as that field.&lt;/p&gt;

&lt;p&gt;Hold up. There is no &lt;code&gt;CreateDate&lt;/code&gt; field. Well done, young padawan. Oddly enough, the MS folks didn't think to have one. So we will need to do it for them. Go back to Azure and select your AdventureWorks database. Click the Query Editor (preview) on the left hand side and log in with the database admin account you provisioned. Run this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;SalesLT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;CreateDate&lt;/span&gt; &lt;span class="nb"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;Product_CreateDateInit&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;GETDATE&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This gets us the &lt;code&gt;CreateDate&lt;/code&gt; field we need along with a default date in it. The first crawl is a &lt;em&gt;NULL&lt;/em&gt; watermark anyway so everything is coming in.&lt;/p&gt;

&lt;p&gt;With that little bonus step out of the way, here's our query for the full crawl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="k"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductCategoryID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;SellStartDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;SellEndDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;DiscontinuedDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ThumbnailPhotoFileName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;rowguid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ProductGuid&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;CreateDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;smalldatetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductCreated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ModifiedDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;smalldatetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductModified&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rowguid&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ModelGuid&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SalesLT&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SalesLT&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ProductModel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;CreateDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;watermark&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Choose &lt;code&gt;DateTime&lt;/code&gt; as the watermark data type and press the Validate Query button. Select the watermark field, which we aliased as &lt;code&gt;ProductCreated&lt;/code&gt;, then select the unique identifier field, which is &lt;code&gt;ProductId&lt;/code&gt;. Notice we have a print out of the first 10 rows of data as well. Interesting side note here: currently &lt;code&gt;money&lt;/code&gt; and &lt;code&gt;float&lt;/code&gt; fields appear to not be supported by the graph connector. That's why &lt;code&gt;ListPrice&lt;/code&gt; was left out of the query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dGLcc9yi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/FullCrawlStep.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dGLcc9yi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/FullCrawlStep.gif" alt="Full Crawl Step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we set the incremental crawl. This will append anything that has been modified since the last incremental crawl run. This step is optional but I recommend it. The crawl looks &lt;em&gt;very&lt;/em&gt; similar to the full crawl, but instead our &lt;code&gt;@watermark&lt;/code&gt; is based on &lt;code&gt;ModifiedDate&lt;/code&gt; instead. Here's the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="k"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductCategoryID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;SellStartDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;SellEndDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;DiscontinuedDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ThumbnailPhotoFileName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;rowguid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ProductGuid&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;CreateDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;smalldatetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductCreated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ModifiedDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;smalldatetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductModified&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rowguid&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ModelGuid&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SalesLT&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SalesLT&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ProductModel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductModelID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;ModifiedDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;watermark&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similar to the full crawl, choose &lt;code&gt;DateTime&lt;/code&gt; as the watermark data type and press the Validate Query button. Select the watermark field, which we aliased as &lt;code&gt;ProductModified&lt;/code&gt;, then select the unique identifier field, which is &lt;code&gt;ProductId&lt;/code&gt;. I skipped the soft delete section for now. I also skipped leveraging any type of row-level security, which is actually supported and documented in &lt;a href="https://docs.microsoft.com/en-us/microsoftsearch/mssql-connector"&gt;Microsoft writeup on the SQL Graph Connectors&lt;/a&gt;. Essentially, you would need to include ACL columnsin the full and incremental crawls, named &lt;code&gt;AllowedUsers&lt;/code&gt;, &lt;code&gt;AllowedGroups&lt;/code&gt;, &lt;code&gt;DeniedUsers&lt;/code&gt;, and &lt;code&gt;DeniedGroups&lt;/code&gt;. Each column is expected to be comma or semicolon delimited and can include UPNs, AAD IDs or Security IDs. I just wanted to see if we could get this data coming back and looking good!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A1Y0pnHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/IncrementalCrawlStep.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A1Y0pnHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/IncrementalCrawlStep.gif" alt="Incremental Crawl Step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last big step is our Manage Schema step. We define what can be queried, searched and retrieved. If an item is found in search, you can only show it in the adaptive card layout if it's been marked as Retrievable, thus added to the schema. So select what you want. I went with anything text-based to be searchable and pulled almost all fields into the schema by marking them as Retrievable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j2Pfek-T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ManageSchemaStep.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j2Pfek-T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ManageSchemaStep.gif" alt="Manage Schema Step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last few steps are a bit of a breeze, especially since I chose not to do ACL columns and row level security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VlI7mhHV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/FinalSteps.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VlI7mhHV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/FinalSteps.gif" alt="Final Steps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Results design and vertical
&lt;/h2&gt;

&lt;p&gt;Our final step is to create our vertical and design the result set. After creating the connector, you'll see some callouts on your new connector in the Required Actions column. You can either click there to set things up or you can access Results Types and Verticals in the Customizations tab. As of the time of this writing, the best order of events is to setup the Result Type first then the Vertical. If you do it the other way, you will have 1 extra step to Enable the Vertical &lt;em&gt;after&lt;/em&gt; you finish setting up your result type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lkvt7x8x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/RequiredActions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lkvt7x8x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/RequiredActions.png" alt="Required Actions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to Adapt
&lt;/h3&gt;

&lt;p&gt;Let's start with the Result Type. Here are the basic steps, which the below GIF flies through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a name for the result type&lt;/li&gt;
&lt;li&gt;Tie it to a Content Source, which will be the new Graph Connector you made&lt;/li&gt;
&lt;li&gt;Apply any display rules (I skipped this)&lt;/li&gt;
&lt;li&gt;Design the layout&lt;/li&gt;
&lt;li&gt;Review and Finish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big thing here is our layout design. We are provided a link on this step to the &lt;a href="https://searchlayoutdesigner.azurewebsites.net/"&gt;Search Layout Designer&lt;/a&gt;. Select a design to start with and Click the Get Started button. This takes you to the designer where you can layer in the fields you want to replace the template with. We want to make some substantial changes, so let's click the Edit Layout button. This layout designer leverages the Adaptive Card schema to do it's magic. Also, any field we set as retrievable and is in the schema is now a field we can display in the layout. Here's what I built:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AdaptiveCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ColumnSet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"columns"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Column"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/mhomol/AdventureWorksThumbs/blob/master/thumbnails/{ThumbnailPhotoFileName}?raw=true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"horizontalAlignment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Center"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"altText"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Not available"&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;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stretch"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Column"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TextBlock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[{Name}](https://somemadeupurl.net/{ProductID})"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bolder"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TextBlock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{Model} ({ProductNumber})"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bolder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warning"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TextBlock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First sold on {{DATE({SellStartDate}, LONG)}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"spacing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small"&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;"horizontalAlignment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Center"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"spacing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Medium"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Column"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FactSet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"facts"&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;"Color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{Color}"&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;"Size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{Size}"&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="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="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;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://adaptivecards.io/schemas/adaptive-card.json"&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;Feel free to paste this into the Layout Payload Editor to see what it will look like. If you want to see a preview of it you'll need sample data to paste into the Sample Data Editor tab. Try this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;"Classic Vest, L"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Classic Vest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ProductNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VE-C304-L"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ProductModified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2008-03-11T10:01:36Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SellStartDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2007-07-01T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ProductId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"866"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ThumbnailPhotoFileName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awc_jersey_male_small.gif"&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;h3&gt;
  
  
  What's the deal with the thumbnail?
&lt;/h3&gt;

&lt;p&gt;Here's the last "special" thing we wanted to add to the heap of "All the Things". In the AdventureWorks Products table, there are Thumbnail binaries and Thumbnail names. Well, of course, I wanted to see these thumbnails come through in the results. &lt;code&gt;Varbinary&lt;/code&gt; fields aren't supported by the crawler, so I had 1 of 2 options: either make an endpoint that would pull the item from the database for the Product ID on any call and return the byte array as the response or pull all of the binaries out of the database once and save them to files elsewhere. I chose the latter. Here's the &lt;a href="https://github.com/mhomol/AdventureWorksThumbs"&gt;source&lt;/a&gt; for it if you want to do something similar yourself. So now I had the files I needed in github, named by the &lt;code&gt;ThumbnailPhotoFileName&lt;/code&gt; field value. So that's how I'm able to include that in my layout.&lt;/p&gt;

&lt;p&gt;Here's a quick rundown of setting up the Result Type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IgbMRUG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ResultTypeSetup.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IgbMRUG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/ResultTypeSetup.gif" alt="Result Type Setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last, but not least, we make our Vertical. It's even simpler.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide a name&lt;/li&gt;
&lt;li&gt;Select the Content Source&lt;/li&gt;
&lt;li&gt;Provide a KQL query (&lt;em&gt;optional&lt;/em&gt; I skipped it)&lt;/li&gt;
&lt;li&gt;Review and Finish&lt;/li&gt;
&lt;li&gt;Click the button to Enable Vertical&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a quick rundown of setting up the Vertical:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--68j9XMSa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/VerticalSetup.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--68j9XMSa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://homol.work/img/blog/gc/VerticalSetup.gif" alt="Vertical Setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Out of the oven
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lttCUaxB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fmedia.tenor.com%252Fimages%252F01fe77ed86bdde9e09ea98626c75ba3a%252Ftenor.gif%26f%3D1%26nofb%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lttCUaxB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://external-content.duckduckgo.com/iu/%3Fu%3Dhttps%253A%252F%252Fmedia.tenor.com%252Fimages%252F01fe77ed86bdde9e09ea98626c75ba3a%252Ftenor.gif%26f%3D1%26nofb%3D1" alt="Finished Product"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what exactly have we cooked up here? Let's head over to a search box somewhere and type something in that we know is a word in the Products or Models. How about &lt;em&gt;mountain&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PRb3PmB3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/MountainSearch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PRb3PmB3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/gc/MountainSearch.png" alt="Search up mountain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So there we have it! It was a lot to toss into the pot, but I think we brought it all together nicely. Hope you've learned a little something and that it gets you thinking about what you want to do next with the new Graph Connectors and what other structured data you may want to start piping into Microsoft Search for your customers and employees. Don't forget to delete this resource group when you're done messing around. Enjoy!&lt;/p&gt;

</description>
      <category>m365</category>
      <category>azure</category>
      <category>sql</category>
      <category>search</category>
    </item>
    <item>
      <title>Mike-rosoft Learn Highlights for July</title>
      <dc:creator>Mike Homol</dc:creator>
      <pubDate>Sun, 21 Jun 2020 01:54:52 +0000</pubDate>
      <link>https://dev.to/mhomol/mike-rosoft-learn-highlights-for-july-5coh</link>
      <guid>https://dev.to/mhomol/mike-rosoft-learn-highlights-for-july-5coh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Like a good nerd, I'm a sucker for gamification and achievements in all of their forms. So I've taken to &lt;a href="https://docs.microsoft.com/en-us/learn/browse/"&gt;MS Learn&lt;/a&gt; badges and trophies like a duck to water. On the plus side, it's already single-handedly gotten me an Azure Developer Associate certification. So I'm giving back by doing a monthly series where I highlight some Learn badges that I felt were exceptional and deserve to be viewed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  This Month's Highlights
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KXh1EHp9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/publish-static-web-app-and-api.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KXh1EHp9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/publish-static-web-app-and-api.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/publish-app-service-static-web-app-api/"&gt;Publish an Angular, React, Svelte, or Vue JavaScript app and API with Azure Static Web Apps&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/ignite"&gt;Microsoft Ignite&lt;/a&gt; was all digital this year but was still pretty fun. It was like a giant &lt;a href="https://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt; event. In that event, John Papa did a great session unveiling Azure Static Web Apps. True to form, almost immediately after that unveiling, this little number showed up on MS Learn. It's great first look at a preview product, where Azure is throwing their hat into the ring with other JAMstack hosting services, like Render, GitHub pages, or GitLabs. I definitely recommend this walkthrough - it's quick, easy and free to try and you get a good glimpse of everything that's supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ccISQjeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/advocates/enable-automatic-updates-in-a-web-app-using-azure-functions-and-signalr.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccISQjeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/advocates/enable-automatic-updates-in-a-web-app-using-azure-functions-and-signalr.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/automatic-update-of-a-webapp-using-azure-functions-and-signalr/"&gt;Enable automatic updates in a web application using Azure Functions and SignalR Service&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SignalR is such a fun piece of technology. I had a blast building this one and watching things work. This is a methodology any developer should keep in their back pocket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kTJn4Q2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/build-serverless-api-with-functions-api-management.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kTJn4Q2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/build-serverless-api-with-functions-api-management.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/build-serverless-api-with-functions-api-management/"&gt;Expose multiple Azure Function apps as a consistent API by using Azure API Management&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have to imaging the Azure API Management can get pretty pricey so I haven't actually done any of this in a production sense, but the lessons surrounding Azure API Management are pretty neat and put a great bow on your API structure. But this particular lesson, which shows you how to pull disparate Azure functions into a single cohesive API, both structurally for you or your organization but also for consumers of said API, is really strong and shows you the true power of Azure API Management&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--db5A_DgQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/build-a-web-app-with-blazor-webassembly-and-vs-code.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--db5A_DgQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.microsoft.com/en-us/learn/achievements/build-a-web-app-with-blazor-webassembly-and-vs-code.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/build-blazor-webassembly-visual-studio-code/"&gt;Build a web app with Blazor WebAssembly and Visual Studio Code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have high hopes for Blazor in the long run. The route of building WebAssembly is some pretty interesting stuff and this is a great introduction to the technology and nicely self-contained. Hopefully it will leave you wanting more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a cross-post from my personal blog &lt;a href="https://homol.work/blog/mikerosoftlearn20200620"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>mslearn</category>
      <category>certifications</category>
      <category>azure</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Amphetimine alternatives?</title>
      <dc:creator>Mike Homol</dc:creator>
      <pubDate>Fri, 05 Jun 2020 15:05:54 +0000</pubDate>
      <link>https://dev.to/mhomol/amphetimine-alternatives-19m9</link>
      <guid>https://dev.to/mhomol/amphetimine-alternatives-19m9</guid>
      <description>&lt;p&gt;I have really enjoyed using the app Amphetimine for my Mac, but I think it is causing my Mac to restart - likely due to the triggered monitoring it does?  For my Mac user friends out there, what is your favorite alternative?  I'm hoping for something that has that similar feature of triggering off of various apps running on the Mac.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Coding with Nate, pt. 1</title>
      <dc:creator>Mike Homol</dc:creator>
      <pubDate>Wed, 06 May 2020 15:07:06 +0000</pubDate>
      <link>https://dev.to/mhomol/coding-with-nate-pt-1-95e</link>
      <guid>https://dev.to/mhomol/coding-with-nate-pt-1-95e</guid>
      <description>&lt;p&gt;This is cross-posted &lt;a href="https://homol.work/blog/codewnate20200504"&gt;here&lt;/a&gt;.  Also, this is my first time posting, so go easy on me lol.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding with Nate
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Adventures in getting your kids interested in coding
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a series of posts I hope to do cataloging some of my progress with spreading the gospel of code to my kids. Recently I made some progress with my son, Nate, and hope to share what we build together in this series. 😊&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part One: Idea and Schema
&lt;/h2&gt;

&lt;p&gt;For many years, I've struggling in fits and spurts to get my kids to embrace coding. I took to it like a duck to water and was coding on this when I was 9 years old:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_AdHKfyA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/trs-80.jpg" alt="Behold the Radioshack TRS-80" width="300"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Behold the Radioshack TRS-80&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I've had a few glimmers of hope, like when they were in robotics and were helping to write the programs, but eventually that died out. Then I had a brief period where my sons were doing lessons on freecodecamp.org. That site is fantastic, by the way. But so far, nothing lasting. But I press on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Something we both like
&lt;/h2&gt;

&lt;p&gt;About a month ago, I challenged my sons to come up with an app idea. My thinking was that they might be more inclined to learn something if it would result in something that originated from their imagination. My son Nate started doing the &lt;a href="https://apps.apple.com/app/id908519492?app=itunes"&gt;Swift Playground&lt;/a&gt; lessons and things were looking up. But as usual, things sputtered out.&lt;/p&gt;

&lt;p&gt;2 weekends ago, we were playing our favorite collector card game, &lt;a href="http://www.upperdeck.com/products/entertainment/marvel/marvel-legendary.aspx#"&gt;Marvel Legendary&lt;/a&gt;. I have amassed pretty much the entire collection and we spent a fair bit of the weekend battling supervillains. There have been some apps made by the community already - namely one called &lt;a href="https://apps.apple.com/us/app/assemble-legendary-randomizer/id698951667"&gt;Assemble&lt;/a&gt;. It randomizing matchups, which is really nice for a game that keeps growing with 3 or 4 expansions a year. But this app was starting to slow down in its updating. Additionally my son voiced his frustration with not being able to search up cards by the text on them or by their features. Suddenly, I saw the light go on and he turned to me and said, "Maybe this is the app we can build."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eureka&lt;/strong&gt;! We had a problem that we wanted to solve and it was surrounding a topic that we both enjoyed. It was the perfect storm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Early Plan
&lt;/h2&gt;

&lt;p&gt;So the basics for the idea are now there. We want a mobile app that will allow for in-depth searching of thousands of cards and that will also randomize setups of games.&lt;/p&gt;

&lt;p&gt;Technically, here's the early plan: a database of cards built in Azure Data Storage, accessible from Azure Functions, via a mobile app built in React Native. We will open source the whole thing, so feel free to contribute or give feedback, especially if you happen to also play the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Homework
&lt;/h2&gt;

&lt;p&gt;My homework for Nate so far is to start going through the JavaScript lessons on freecodecamp.org. Send me thoughts if you have some better ideas. My thinking is for him to try and pick up some basics of JavaScript while we're building out the backend. While he's learning, he's volunteered to help with data entry. We'll see how long that lasts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking at Cards
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w_233HWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/legendary-cards.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w_233HWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/legendary-cards.jpg" alt="Sooo many cards!" width="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our first order of business was getting the data figured out. My first real teachable moment. We examined various cards and started making notes, first in bullet lists of the various types of cards and the properties we were seeing on them. Here are some examples.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mastermind&lt;/th&gt;
&lt;th&gt;Hero&lt;/th&gt;
&lt;th&gt;Villian&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fLA3BQsm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/darak-phoenix-01.png" alt="Dark Phoenix Mastermind" width="200"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yiD8lde8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/deadpool-03-1.jpg" alt="Deadpool" width="200"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--22VlvZ8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/superhuman-registration-act-04.jpg" alt="She-Hulk Villain" width="200"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see, there are many various qualities and this is just a small sample. In fact, just at the top-most level, there are 10 types of cards: &lt;em&gt;Wound, Token, Officer, Sidekick, Bystander, Scheme, Enemy Leader, Enemy Support, Enemy Group, Playable&lt;/em&gt;. Pretty quickly in, we switched to a JSON document and started going over samples of each card type, appending properties to the same single JSON as we discovered new things on a card. This actually sunk in with him. Seeing the JSON get updated live as we were reviewing information on a card was like seeing the objects and properties come to life real-time on the screen. Here's what we ended up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"StartingDeck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hero | Villain | Officer | Sidekick | Wound | Bystander | Mastermind | Token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wound | Token | Officer | Sidekick | Bystander | Scheme | Enemy Leader | Enemy Support | Enemy Group | Playable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Classification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wound | Grievous Wound | Bindings | Villain | Officer | Madame Hydra | Hero | Special Sidekick | Bystander | Recruitable Bystander | Scheme | Plot | Mastermind | Commander | Henchmen | Backup Adversaries | Villain | Adversary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Team"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Shield | Avengers | X-Men | Champions | Fantastic Four | Heroes of Asgard | Sinister 6 | Hydra | Foes of Asgard | Crime Syndicate | Brotherhood | Cabal | Guardians of the Galaxy | Illuminati | Marvel Knights | Mercs for Money | New Warriors | Spider Friends | Venomverse | Warbound | X-Force"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Instinct | Ranged | Strength | Covert | Tech | Basic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Yellow | Blue | Green | Red | Silver | Grey"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Ability"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"Keywords"&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;"Healing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Betrayal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Ambush"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Human Shield"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Phasing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Fight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Escape"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Overrun"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Fight or Fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"X Uru-Enchanted Weapon"&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;"CombinationSymbols"&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;"CombinationEffect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"Expansion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Core | Villains | Civil War | X-Men | S.H.I.E.L.D."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AlwaysLeads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"CommandMasterStrike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"VictoryPoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Attack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Recruit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"RecruitCost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsRecruitable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Setup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"Twist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"NumTwists"&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;"1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&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;"NumHeros"&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;"1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&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;"NumVillains"&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;"1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&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;"SchemeWins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"SpecialRules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;Seeing as we will have to start simple, we will begin by manually creating JSON docs for cards, until we get a UI going. So to try and make it easier on us, especially Nate, I set out to make a schema for this sample doc. This route would give us intellisense and document validation in a good editor, like VS Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Schema
&lt;/h2&gt;

&lt;p&gt;This was my first foray into JSON Schema. I started at the source and read through this walkthrough: &lt;a href="https://json-schema.org/learn/getting-started-step-by-step.html"&gt;Getting Started Step-by-step&lt;/a&gt;. That gave me most of the tools I needed to understand what was going on. Essentially, you're setting up type definitions and other rules as you identify them.&lt;/p&gt;

&lt;p&gt;That said, it was still a pretty big doc for me to try and render out the schema manually, so I started with a schema generator - found &lt;a href="https://www.jsonschema.net/home"&gt;here&lt;/a&gt; - and applied changes from there, namely titles and descriptions, as well as identifying things we missed as I was validating fields. The generator helps a lot with following along, as you can compare your node to the schema generated. The only big thing I had to learn how to add was the &lt;code&gt;enum&lt;/code&gt; property. This is a great option for string properties. It allows you to provide an array of options for editors to leverage. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"enum"&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="s2"&gt;"Yellow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Silver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Grey"&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 here's what happens in VS Code when you reference the schema and attempt to add a color field to the document:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BOTE9WIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/color-enum-results.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BOTE9WIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://homol.work/img/blog/color-enum-results.png" alt="End result in VS Code" width="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty cool, huh? Well I thought so at least lol.&lt;/p&gt;

&lt;h2&gt;
  
  
  'Til next time
&lt;/h2&gt;

&lt;p&gt;So far, the schema is all we have and we're starting to create the data for Azure Storage. I'll share more as we make progress. Hopefully he stays interested and we actually produce a working product in the App Store. We shall see.&lt;/p&gt;

&lt;p&gt;The full schema is published here: &lt;a href="https://homol.work/json/legendarydb/card-schema.json"&gt;https://homol.work/json/legendarydb/card-schema.json&lt;/a&gt;&lt;/p&gt;

</description>
      <category>teaching</category>
      <category>javascript</category>
      <category>reactnative</category>
      <category>azure</category>
    </item>
  </channel>
</rss>
