<?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: Christopher Harrison</title>
    <description>The latest articles on DEV Community by Christopher Harrison (@geektrainer).</description>
    <link>https://dev.to/geektrainer</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%2F82036%2F96c961c5-3e77-4f62-b5a5-9bd7cbac02c5.jpg</url>
      <title>DEV Community: Christopher Harrison</title>
      <link>https://dev.to/geektrainer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geektrainer"/>
    <language>en</language>
    <item>
      <title>Provide context to GitHub Copilot Chat</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Tue, 10 Sep 2024 18:01:03 +0000</pubDate>
      <link>https://dev.to/github/provide-context-to-github-copilot-chat-24op</link>
      <guid>https://dev.to/github/provide-context-to-github-copilot-chat-24op</guid>
      <description>&lt;p&gt;Context is key. This is true across all forms of communication, including with generative AI assistants like GitHub Copilot. When you're interacting with GitHub Copilot Chat, there's numerous features available to you to help point Copilot in the right direction, to help it understand what you're looking for. In turn, the suggestions you'll receive will improve! Let's walk through some of the most powerful techniques to help you get the most out of the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Highlight the code
&lt;/h2&gt;

&lt;p&gt;Let's say I'm trying to understand a block of code, improve its performance, or discover any security flaws. The first thing Copilot needs to know is the code I'm referring to. You can do this by highlighting the code in question. This will focus Copilot's attention on that block, and it will respond based on what it sees.&lt;/p&gt;

&lt;p&gt;One thing you'll notice in the Chat window after you send a message is a &lt;strong&gt;references&lt;/strong&gt; widget. If you expand this widget you'll be able to see what Copilot considered when crafting its answer. If you ever ask a question and the response doesn't relate to what you expected, check the references section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp338w4ziti0nnfpvfxq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp338w4ziti0nnfpvfxq.gif" alt="Video of code being highlighted, asking GitHub Copilot Chat what the code does, then focusing on the references widget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use slash commands for quick access to common questions
&lt;/h2&gt;

&lt;p&gt;Copilot is great at tasks like explaining code, suggesting fixes, and generating tests. In fact, these are three of the most common workloads for Copilot, so much so that there's shortcuts to help you do these with minimal typing!&lt;/p&gt;

&lt;p&gt;For frequently used pieces of functionality, Copilot Chat provides slash commands. These include &lt;code&gt;/tests&lt;/code&gt; for generating unit tests or &lt;code&gt;/fix&lt;/code&gt; to have Copilot determine a fix for buggy code. You can list all the commands available by using &lt;code&gt;/help&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt; After adding a &lt;code&gt;/&lt;/code&gt; command, make sure you press Tab to activate it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Expand beyond the current file with workspace
&lt;/h2&gt;

&lt;p&gt;One thing you might notice about several of the slash commands is the addition of &lt;code&gt;@workspace&lt;/code&gt;. In a nutshell, this allows Copilot to create an index of your workspace (or project), and build a response to your prompt holistically. This is rather powerful when considering multiple files is important to providing the correct code. In the example below, we have a code block which uses a service defined in a separate file. If we use &lt;code&gt;/explain&lt;/code&gt; which includes the &lt;code&gt;@workspace&lt;/code&gt; agent we can see the updated &lt;strong&gt;references&lt;/strong&gt; widget includes not just the current file but also the source code for the service. This allows for a more robust answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft93983h99nygxoiy5xoq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft93983h99nygxoiy5xoq.gif" alt="Clip of using /explain with @workspace and how the references will now include additional files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Be specific about the important files
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@workspace&lt;/code&gt; uses the entire workspace. But what if we know exactly what files are important to the question being asked? Let's say I'm adding some JavaScript where we need to find an element by its ID and use some CSS classes defined in a stylesheet? By using &lt;code&gt;#file&lt;/code&gt; we can point Copilot at those specific files, which we can again see in the references widget, increasing the quality of code.&lt;/p&gt;

&lt;p&gt;In my example I have an HTML file with an element with an ID of &lt;code&gt;name-display&lt;/code&gt;. I have a CSS class named &lt;code&gt;message-header&lt;/code&gt;. If I can't remember the exact names (which is pretty typical for me (and I think many developers)), I'd have to open up each file individually, explore to find the names, and then code. With &lt;code&gt;#file&lt;/code&gt; I can point Copilot at the files, then just describe what I need. Copilot will intuit the rest for me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrsukdio51wsjouje7e3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrsukdio51wsjouje7e3.gif" alt="Video showing if you use #file you can select specific files to add to context. The text explains that we need to use the name display from #file:index.html and the message class from #file:index.css"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterate and build together
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot has the tagline of "Your AI pair programmer". This is the perfect description of how best to interact with Copilot. If we think about talking to a coworker, or really any other person, there's often some back and forth which takes place before we find the answer we're seeking. In the example below, I asked Copilot to generate a search function by distance, which it did. But what if we wanted this to be a range rather than equality. If we provide more information we'll get the code we're looking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16dahoi4st6jtxe82w3t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16dahoi4st6jtxe82w3t.gif" alt="Video demonstrating chat where we start by asking for a function to search races by distance. Copilot gives us a function based on equality. We then follow up by clarifying we want to search by a range, and Copilot updates its response based on the new context."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;As I highlighted at the top, context is key to communication. The better we help Copilot understand what we're looking for and what's important the better the responses will be. Using the techniques above to help focus Copilot's attention will allow you to move that much faster and stay in the zone.&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubcopilot</category>
      <category>generativeai</category>
      <category>ai</category>
    </item>
    <item>
      <title>Getting rid of those console.log('here') statements with GitHub Copilot</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Tue, 16 Jul 2024 17:30:55 +0000</pubDate>
      <link>https://dev.to/github/cleaning-up-debug-code-with-github-copilot-4ooc</link>
      <guid>https://dev.to/github/cleaning-up-debug-code-with-github-copilot-4ooc</guid>
      <description>&lt;p&gt;There are two types of developers in the world - those who use &lt;code&gt;console.log('here!')&lt;/code&gt; for debugging and then check that code in, and... Actually, I take that back. There's one type of developer in the world. Fortunately, GitHub Copilot can help us clean that up really quickly.&lt;/p&gt;

&lt;p&gt;I've got some code with debug statements embedded. I'm also grabbing a temp variable for some data which I would normally just return directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Runners:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;runners&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;runners&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error getting all runners:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error getting runner by id "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;":`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sanitized_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sr"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error getting runners by name "%s":`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sanitized_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to clean all of that up. I highlight the code (which sets the context for GitHub Copilot Chat), then ask GitHub Copilot Chat "Remove any debug statements and any unnecessary variables".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhdwn4ntv9o3y4iq0pgld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhdwn4ntv9o3y4iq0pgld.png" alt="Screenshot of GitHub Copilot Chat requesting chat to Remove any debug statements and any unnecessary variables" width="722" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within just a few moments, Copilot returns back my cleansed code which I can paste into my editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error getting all runners:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error getting runner by id "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;":`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error getting runners by name "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;":`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, should I learn to use the debugging capabilities of Visual Studio Code instead of relying on strategies from decades ago? Probably. :D But until that happens, I can at least cleanup everything quickly and efficiently with Copilot.&lt;/p&gt;

&lt;p&gt;I think one of the things which is often overlooked about GitHub Copilot is it's not just about creating new code, but also performing other related tasks and cleanup. When you come across a situation similar to this, where you're worried something might take a while, ask Copilot. You might just find it's able to perform the task with just a couple of quick questions. What have you been able to offload to Copilot which surprised you? Comment below!&lt;/p&gt;

</description>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Working with GitHub Copilot as your AI pair programmer</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Tue, 06 Feb 2024 22:49:00 +0000</pubDate>
      <link>https://dev.to/github/working-with-github-copilot-as-your-ai-pair-programmer-4997</link>
      <guid>https://dev.to/github/working-with-github-copilot-as-your-ai-pair-programmer-4997</guid>
      <description>&lt;p&gt;Recently I was building out a demo which used &lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django&lt;/a&gt;. I wanted to streamline the setup of the demo with a starter script to create and populate the database. This task fell squarely under the "I know this is possible but can't quite remember how to do it" umbrella. Normally I'd be stuck digging through the docs, copying and pasting snippets, and hoping the "Franken-code" I was building would actually work.&lt;/p&gt;

&lt;p&gt;Instead I was able to rely on generative AI to build out my sample data and GitHub Copilot to generate the code. I was honestly amazed at how much work Github Copilot was able to do for me. It also served as a great use case in how to best prompt and work with Copilot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;The sample app I was building is a website for a conference. I needed to create a setup script which would:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check to see if a local SQLite database was already created.&lt;/li&gt;
&lt;li&gt;Assuming no database existed, &lt;a href="https://docs.djangoproject.com/en/5.0/ref/django-admin/#django-admin-migrate" rel="noopener noreferrer"&gt;run the migration scripts&lt;/a&gt; to create the database.&lt;/li&gt;
&lt;li&gt;Prompt the user for their name, email and password, and create a &lt;a href="https://docs.djangoproject.com/en/5.0/topics/auth/default/#creating-superusers" rel="noopener noreferrer"&gt;superuser&lt;/a&gt; with this info.&lt;/li&gt;
&lt;li&gt;Populate the database with the users and talks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, these are all things I know are possible, but just am not sure how to do it. I also didn't want to create a bunch of data on my own. It was time to rely on a little bit of AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the data
&lt;/h2&gt;

&lt;p&gt;While it's possible for GitHub Copilot to generate text (it does support Markdown, for example), it wasn't going to be the appropriate tool to create a bunch of sample data in CSV files. So I turned to ChatGPT to ask it to create CSV files for me, one with a list of names for my speakers, and another with a list of talks. The latter task I walked through a few times to create different tracks for a full collection of talks. While it took a little bit of manipulation, and I had two CSV files ready to go in just a few minutes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: GitHub Copilot is a tool, and just like every tool it has its best uses. Generating CSV files isn't an ideal scenario for Copilot, but it worked perfectly with ChatGPT.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating the file structure
&lt;/h2&gt;

&lt;p&gt;Django supports &lt;a href="https://docs.djangoproject.com/en/5.0/howto/custom-management-commands/" rel="noopener noreferrer"&gt;custom commands&lt;/a&gt; which can be called just as you would the built-in commands like &lt;code&gt;createsuperuser&lt;/code&gt; or &lt;code&gt;startapp&lt;/code&gt;. That much I knew; I just didn't know how to actually do it. So I asked chat in VS Code &lt;strong&gt;"How do I create custom scripts in Django?"&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Chat gave me information about how to create the file and folder structure necessary for the command, even though I used the wrong terminology. While I'm certainly going to increase the chances I get the right answer by using the right terminology, I appreciated the bit of flexibility offered to me by Copilot.&lt;/p&gt;

&lt;p&gt;The answer provided says to put the code into an existing folder, but I really want this to be separate. So I created a new folder in the project and duplicated the structure in as indicated in the chat reply. The results looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scripts/

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;init&lt;/strong&gt;.py (empty file)&lt;/li&gt;
&lt;li&gt; management/

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;init&lt;/strong&gt;.py (empty file)&lt;/li&gt;
&lt;li&gt; commands/

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;init&lt;/strong&gt;.py (empty file)&lt;/li&gt;
&lt;li&gt; demo-setup.py (where my code will go)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I finished the initial setup by &lt;a href="https://docs.djangoproject.com/en/5.0/ref/applications/" rel="noopener noreferrer"&gt;registering the application&lt;/a&gt;, something I was already familiar with based on my experience with Django.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: GitHub Copilot is not a replacement for developers. It won't do everything for you, and you won't be able to suddenly program in a language or framework you've never seen just by using Copilot. But it'll certainly help augment your understanding and aid your learning!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating the scaffolding
&lt;/h2&gt;

&lt;p&gt;OK, project structure setup. Now it was time to start writing code. Coding is always an iterative process, regardless of the toolset we're using. So my first goal is to get some code into place, then start updating and adding features as needed.&lt;/p&gt;

&lt;p&gt;Upon opening the newly created &lt;strong&gt;demo-setup.py&lt;/strong&gt; file, I used Cmd-I to open the inline chat window in VS Code. I described at a high level what I was trying to do so I could get some code to start.&lt;/p&gt;

&lt;p&gt;The prompt:&lt;/p&gt;

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

Create a custom command which checks if the sqlite database exists, and if not runs migrations, prompts for superuser information, and populates database from CSV files


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

&lt;/div&gt;

&lt;p&gt;The initial code started with this:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.management.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MyModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Check if SQLite database exists, run migrations, prompt for superuser info, and populate database from CSV files&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Check if SQLite database exists
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;db.sqlite3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Run migrations
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Running migrations...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: One of the best use cases for Copilot is to generate scaffolding. Pretty much every framework available has some level of ceremony, some set of boilerplate code which needs to be built out. Let Copilot generate that and the initial code, then you can focus on the more important pieces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Improving the code
&lt;/h2&gt;

&lt;p&gt;The code provided was a good first iteration. But I really prefer to have helper functions rather than a single function for the entire script. I find it's more readable and easier to maintain. So, back to Copilot Chat I went. I highlighted the code in my Python file and asked chat "Please refactor this to use helper functions."&lt;/p&gt;

&lt;p&gt;While the "please" certainly isn't necessary, the output was exactly what I wanted. To focus on the &lt;code&gt;handle&lt;/code&gt; function, which is the entry point to the command, it's now calling a bunch of helper functions, all of which were created by Copilot.&lt;/p&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;db.sqlite3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_migrations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_superuser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;populate_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SQLite database already exists.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: The goal of Copilot is to aid developers as they write code. Just as the first iteration I write won't typically be the final product, the same holds true with Copilot. I'm constantly going back to make updates to what I write, a process which continues with Copilot. The fact the initial iteration was written by Copilot for me saves me a lot of time, and editing what's there is faster than me writing it all from scratch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Customizing for my environment
&lt;/h2&gt;

&lt;p&gt;The application I built uses a custom user object, rather than the default &lt;code&gt;User&lt;/code&gt; in Django. The line &lt;code&gt;from django.contrib.auth.models import User&lt;/code&gt; is going to import said generic &lt;code&gt;User&lt;/code&gt;, not the custom one.&lt;/p&gt;

&lt;p&gt;As already highlighted, coding is an iterative process. Copilot already did a lot of work here, now I just need to begin making some changes to get the code closer to what I want.&lt;/p&gt;

&lt;p&gt;I added removed the import statement, and added in a couple of comments:&lt;/p&gt;

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

&lt;span class="c1"&gt;# Get the custom user model
&lt;/span&gt;

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

&lt;/div&gt;

&lt;p&gt;which generated:&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And then:&lt;/p&gt;

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

&lt;span class="c1"&gt;# Set User to the custom user
&lt;/span&gt;

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

&lt;/div&gt;

&lt;p&gt;which gave me:&lt;/p&gt;

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

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: Specificity and context matters. Because the only file I had open was the script file, Copilot was unaware I was using a custom &lt;code&gt;User&lt;/code&gt;. With a couple of quick comments where I provided more information, I was able to update the code to get the custom user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Fast forwarding to the end
&lt;/h2&gt;

&lt;p&gt;From there, it was time to flesh out the script, add in the necessary logic, and build the rest of the functionality. Through the process I relied on code completion (ie: adding comments to my code) when I had a clear understanding of what I needed, and chat when I needed to ask questions and be a bit more interactive.&lt;/p&gt;

&lt;p&gt;In the course of about an hour, with me admittedly on a conference call which I was "monitoring", I was able to generate about 70 lines of code (counting comments). You can see the &lt;a href="https://gist.github.com/GeekTrainer/63a6a5c21ea8ba31d7169e18383f34d6" rel="noopener noreferrer"&gt;finished command&lt;/a&gt;. I cleaned up a few comments, which I typically don't do (not really sure why I did that in this case).&lt;/p&gt;

&lt;p&gt;You'll notice in the &lt;a href="https://gist.github.com/GeekTrainer/63a6a5c21ea8ba31d7169e18383f34d6#file-demo-setup-py-L53" rel="noopener noreferrer"&gt;last function which populates the database&lt;/a&gt; I gave a pretty long set of comments to describe exactly what I wanted to do. This is certainly a lot of typing, but given I wasn't sure how to do it off the top of my head, it was much faster than the traditional methods of going to Google.&lt;/p&gt;

&lt;p&gt;The last thing you might see is a relatively large delta from some of the names used in the initial code and the final result. This is largely due to how I write code, that I typically need to see things to help crystalize in my brain how I actually want them implemented. It's also one of the things I really like Copilot for; it allows me to just try things, to prototype, and then go back and change them as I figure out what it is I'm trying to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I've always liked the tagline of GitHub Copilot as "Your AI pair programmer." I find if you think of it like that, you tend to get the best results. When I'm working with someone else I don't expect them to have all the answers, just as I don't either. We'll work together to generate the necessary code, working iteratively, trying things, changing things, until we get the result we need.&lt;/p&gt;

&lt;p&gt;In this example here, I started by effectively saying, "I know this is possible... How do I do this?", and I was off and running. I wrote some code, I asked some questions, I made some updates. And in less than an hour I had the entire script/command built out. Copilot has streamlined the way I write code.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>githubcopilot</category>
      <category>devrel</category>
      <category>github</category>
    </item>
    <item>
      <title>Three tricks to rolling out GitHub Copilot to your team</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Tue, 02 Jan 2024 19:21:01 +0000</pubDate>
      <link>https://dev.to/github/three-tricks-to-rolling-out-github-copilot-to-your-team-1m07</link>
      <guid>https://dev.to/github/three-tricks-to-rolling-out-github-copilot-to-your-team-1m07</guid>
      <description>&lt;p&gt;At GitHub Universe I had several conversations with customers about their rollout of GitHub Copilot. While they loved the product, they were flummoxed as to why their rollout stagnated. They saw an early uptake of adoption which leveled off, and in some cases even decreased. What happened? What went wrong?&lt;/p&gt;

&lt;p&gt;What if I told you there's a few simple things you can do to ensure a successful rollout of GitHub Copilot and drive adoption. The third will surprise you!&lt;/p&gt;

&lt;h2&gt;
  
  
  Teach them to fish
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub Copilot isn't just a flashy demo. It's a productivity tool, and should be treated as such.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the thing - GitHub Copilot is a tool, just like your &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment"&gt;IDE&lt;/a&gt; is a tool. And developers need to learn how to use the tool, just like, well, any other tool. We need to &lt;a href="https://en.wiktionary.org/wiki/give_a_man_a_fish_and_you_feed_him_for_a_day;_teach_a_man_to_fish_and_you_feed_him_for_a_lifetime"&gt;teach them to fish&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This isn't about your developers throwing out everything they know about writing code and starting over, but rather adding a few new &lt;a href="https://github.blog/2023-06-20-how-to-write-better-prompts-for-github-copilot/"&gt;skills and techniques&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Help your developers learn where GitHub Copilot shines, and the workloads it does best with. It can help developers with syntax they often have to look up like regular expressions. Or allow them to offload code they don't like to write, like unit tests, or data transfer objects, or unit tests, or boilerplate code, or unit tests. (Did I mention unit tests?)&lt;/p&gt;

&lt;p&gt;There's also a skill to be learned in crafting prompts and interacting with any AI tool, including GitHub Copilot. A bit of time spent working with your team to learn how best to write comments or manage code to generate better code will drive productivity and happier developers.&lt;/p&gt;

&lt;p&gt;This doesn't need to be formal classroom training (although that can certainly help). It can take the form of lunch and learns, or a self-guided workshop, or by allowing your internal influencers to influence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Influencers influence
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.dictionary.com/browse/influencer"&gt;&lt;strong&gt;in&lt;/strong&gt;-floo-*uh*n-ser&lt;/a&gt; (n): a person who has the power to influence many people, as through social media or traditional media&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the word influencer might conjure up images of Instagram and TikTok, you have internal influencers. These are the front-line managers and senior developers people look up to. We all know the importance of executive buy-in; gaining the support of your influencers is just as important.&lt;/p&gt;

&lt;p&gt;Your influencers will help shape the opinion your developers have about any new tools, including GitHub Copilot. They're the ones your developers look to when they have questions or get stuck.&lt;/p&gt;

&lt;p&gt;Help your influencers influence. Provide them with the resources to support their teams. Encourage them to be proactive, to post to Slack, and to send emails to the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not all email is spam
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;We've been trying to reach you about your car's extended warranty...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I know. It's 2024. Who still reads email, right? Turns out, everyone. While it may not be as frequent, people do, in fact, read their email. Email can serve as a great reminder for someone to take action.&lt;/p&gt;

&lt;p&gt;When our senior researcher who investigates such things told me this one simple trick I didn't believe her. Yet, it actually works. Send reminder emails.&lt;/p&gt;

&lt;p&gt;When developers are first given access to GitHub Copilot they'll receive an email with instructions on how to install it, but there isn't an automatic follow-up process. Craft a couple of emails to send out over the next handful of weeks talking about GitHub Copilot, highlight some common use cases, and you'll notice more developers will start using it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The more things change
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Old techniques continue to work even when we're talking about new tools&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nothing laid out above is new. Training, influencers and reminders are key to successfully rolling out any changes. But from my experience there does seem to be something a bit different about the way people perceive GitHub Copilot. It feels as though it's magic at times, almost self-explanatory. This leads to a "set it and forget it" mentality where it's "flipped on" without the necessary steps in place to ensure success.&lt;/p&gt;

&lt;p&gt;There doesn't need to be a lot of formalities involved. But taking these steps can help ensure your organization gets the most out of &lt;a href="https://github.com/features/copilot"&gt;GitHub Copilot&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Technology is boring</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Mon, 25 Sep 2023 19:36:00 +0000</pubDate>
      <link>https://dev.to/geektrainer/technology-is-boring-1bed</link>
      <guid>https://dev.to/geektrainer/technology-is-boring-1bed</guid>
      <description>&lt;p&gt;Is that a salacious title just to get views? Maybe. Is there some truth to it? Absolutely. Technology is boring. Or more specifically, technology for technology's sake is boring. But so often we as content creators try to teach others by focusing on the technology, not the part which makes it interesting and exciting.&lt;/p&gt;

&lt;p&gt;Technology is interesting because of the problems the tech actually solves. Tech for tech's sake is boring.&lt;/p&gt;

&lt;p&gt;Let me start with an analogy, then talk about the impact it has on us as content creators/presenters/teachers.&lt;/p&gt;

&lt;h2&gt;
  
  
  It goes to 11
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Nigel Tufnel : The numbers all go to eleven. Look, right across the board, eleven, eleven, eleven and...&lt;/p&gt;

&lt;p&gt;Marty DiBergi : Oh, I see. And most amps go up to ten?&lt;/p&gt;

&lt;p&gt;Nigel Tufnel : Exactly.&lt;/p&gt;

&lt;p&gt;Marty DiBergi : Does that mean it's louder? Is it any louder?&lt;/p&gt;

&lt;p&gt;Nigel Tufnel : Well, it's one louder, isn't it? It's not ten.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is Spinal Tap (1984)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;My partner isn't a dork about technology the way I am. While I'll get all excited about the specs of a new phone or a wall outlet with USB chargers, it doesn't connect with her. There will be times where I breathlessly highlight some new feature and she'll look at me, blink her eyes, and say, "It goes to 11?", referencing the scene above.&lt;/p&gt;

&lt;p&gt;The movie This is Spinal Tap is a mockumentary about a rock band. The scene involves the reporter Marty talking to Nigel about his equipment, with Nigel completely confused as to why Marty doesn't understand that 11 is one louder than 10.&lt;/p&gt;

&lt;p&gt;When I turn to my partner and babble about the power of the GPU in the PC I want to build I'm playing the role of Nigel to her Marty. I'm rattling on about something which is meaningless to her, because she doesn't have the context or any reason to care about what I'm talking about.&lt;/p&gt;

&lt;p&gt;Sadly, this is the same approach many presenters and writers take when talking about technology. They get so excited about the tech because it's meaningful to them, yet they forget their audience might not share their experience or passion. They're simply saying, "It goes to 11", perplexed why their audience doesn't get it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop leading with technology
&lt;/h2&gt;

&lt;p&gt;I'm not going to call anyone out, so I won't be using real examples, but consider the following blog or conference session titles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using GitHub Codespaces and containers&lt;/li&gt;
&lt;li&gt;Deep dive into GitHub Actions&lt;/li&gt;
&lt;li&gt;Overview of ASP.NET, MVC and Razor&lt;/li&gt;
&lt;li&gt;Use SETAC, WEAT, DAT and other great frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Editor's note: As far as I know, none of those for the last one abbreviations are real technologies, but if they are it further speaks to the point I'm hoping to make here.)&lt;/p&gt;

&lt;p&gt;When you read those titles what are you able to glean from them with regards to the topic? We know the name of the tech, and contextually we might be able to determine a bit of info about them. But what problem does it solve? What in that title indicates what I should care about, about how it connects to my work? What will I be able to do after viewing your content?&lt;/p&gt;

&lt;p&gt;Or, put more directly, when reading those titles do I get an answer to the question "Why should I care?"&lt;/p&gt;

&lt;p&gt;I don't think so.&lt;/p&gt;

&lt;p&gt;Unfortunately, as technologists, we so often get caught up in our own excitement we forget not everyone has our experience. We've become Nigel, repeatedly saying "It goes to 11," unsure about why people don't understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speak to your audience, not yourself
&lt;/h2&gt;

&lt;p&gt;If you're looking at those titles and it immediately clicks, ask if you're maybe reading more into it based on your experience, adding context which doesn't actually exist. It's a common trap, one into which I've fallen many times. It's easy to get tunnel-visioned, to forget that not everyone has shared our journey, our experience.&lt;/p&gt;

&lt;p&gt;But even if the title does resonate, ask the question - what will those sessions or articles actually cover? One might be able to venture an educated guess, but it's tough to tell. Even when we are leading with technology we're familiar with we're still not telling a good story. And isn't that our primary goal - to tell a great story to share knowledge?&lt;/p&gt;

&lt;h2&gt;
  
  
  Lead with the problem
&lt;/h2&gt;

&lt;p&gt;Instead, titles should lead with the action, answering the question "What will I do with the tech?", followed by the tech. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contribute to projects without the setup with GitHub Codespaces&lt;/li&gt;
&lt;li&gt;Improve and scale DevOps workflows with GitHub Actions &lt;/li&gt;
&lt;li&gt;Create your first website with ASP.NET&lt;/li&gt;
&lt;li&gt;Build mobile apps with SETAC, WEAT and other popular frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note the core difference in the rewrites. It's now made clear what the session/article will cover, the problems the tech can solve, and why someone should care. I can quickly determine if it's applicable to me, to something I want to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking it to the streets
&lt;/h2&gt;

&lt;p&gt;Writing in this style takes a little practice, as it's very easy to fall back to old patterns. But we need to remember our audience and the goal of writing titles and abstracts - it's to convey what one would learn and why they should care. Start with the problem, with an action, of what the learner will be able to do, rather than the tech.&lt;/p&gt;

&lt;p&gt;Because tech for tech's sake is boring.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI isn't the solution to all problems</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Wed, 26 Jul 2023 17:11:00 +0000</pubDate>
      <link>https://dev.to/github/ai-isnt-the-solution-to-all-problems-4odp</link>
      <guid>https://dev.to/github/ai-isnt-the-solution-to-all-problems-4odp</guid>
      <description>&lt;p&gt;There's an old saying "If the only tool you have is a hammer, everything looks like a nail." The basic message is if you're using a single solution you're likely to force its usage to solve every problem, even if it isn't the best tool for the job. This is a trap we often fall into when we're handed a new shiny tool, like AI. We immediately want to apply it to every scenario, even when there are existing options which are better equipped. I'm seeing this quite a bit these days with AI, with new products capturing the imagination of developers everywhere. But before we reach for AI we need to stop to ask if this is the right tool or is a better tool already available.&lt;/p&gt;

&lt;p&gt;As an example, I recently attended a hackathon where a team was building an app to help developers create accessible websites. They were asking questions about how to incorporate AI into the process, using AI to detect accessibility shortcomings. As it turns out, this is a solved problem.&lt;/p&gt;

&lt;p&gt;Looking at web development specifically, there's a set of &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noopener noreferrer"&gt;clearly defined standards&lt;/a&gt;. There are numerous tools, including &lt;a href="https://webhint.io/docs/user-guide/extensions/vscode-webhint/" rel="noopener noreferrer"&gt;Visual Studio Code extensions&lt;/a&gt; and &lt;a href="https://github.com/marketplace/actions/web-accessibility-evaluation" rel="noopener noreferrer"&gt;GitHub actions&lt;/a&gt; which can detect and report on gaps in compliance. Because detection is pattern based, there isn't a need for the dynamic capabilities AI would bring to the table. While it's certainly possible to build a new AI-driven tool, it wouldn't improve the process. This falls into the "hammer/nail" category.&lt;/p&gt;

&lt;p&gt;However, there is a space where AI an help developers improve the accessibility of the apps they build. When we look at existing tools, the feedback provided to developers is relatively generic. An error might be raised indicating an &lt;code&gt;alt&lt;/code&gt; attribute is missing from an &lt;code&gt;img&lt;/code&gt; tag, but it would likely lack explanatory context. It's always better for someone to truly understand the rationale behind a rule rather than following the rule "because someone said so." Why is the &lt;code&gt;alt&lt;/code&gt; attribute important? What makes for good alt text? What are the best practices?&lt;/p&gt;

&lt;p&gt;Using a tool like &lt;a href="https://github.com/github-copilot/chat_waitlist_signup/join" rel="noopener noreferrer"&gt;GitHub Copilot Chat&lt;/a&gt;, a developer could highlight a block of code and ask questions like the ones listed above. It's a great opportunity to interactively learn more about accessibility, the experience different users have on a website, and how best to ensure the pages they build are usable by everyone. The information will be contextual to their specific situation, making it more relevant and impactful to the developer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt; can also aid developers in creating accessible code. GitHub Copilot offers suggestions based both on its model and the current development context. If the HTML the developer is editing follows good accessibility practices, GitHub Copilot is more likely to make suggestions which do the same. A developer can also prompt GitHub Copilot by saying things like "Create a link to /login using the login.png image ensuring accessibility", which helps guide the suggestions generated.&lt;/p&gt;

&lt;p&gt;In the end, we use different tools with different technologies to help our developers create accessible web pages. Extensions in the &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment" rel="noopener noreferrer"&gt;IDE&lt;/a&gt; alert to potential gaps. Automation integrated into the &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="noopener noreferrer"&gt;CI&lt;/a&gt; process catch issues before they're merged into the codebase. And finally AI helps the developer write better code, gain context and learn about accessibility.&lt;/p&gt;

&lt;p&gt;All of us have a propensity to fall into the trap of wanting to use the cool new technology anywhere and everywhere, even if it's not an appropriate application. We always need to stop for a minute to ensure we're using the right tool, that we're not simply hammering everything as not everything is a nail. AI doesn't replace existing tools and solutions; it's another tool we can use to enhance and improve what we already have.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>a11y</category>
      <category>devops</category>
    </item>
    <item>
      <title>Starting a project with Svelte and Azure Static Web Apps</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Fri, 20 Aug 2021 17:47:26 +0000</pubDate>
      <link>https://dev.to/geektrainer/starting-a-project-with-svelte-and-azure-static-web-apps-1da2</link>
      <guid>https://dev.to/geektrainer/starting-a-project-with-svelte-and-azure-static-web-apps-1da2</guid>
      <description>&lt;p&gt;I love &lt;a href="https://docs.microsoft.com/azure/static-web-apps/overview?WT.mc_id=academic-39081-chrhar"&gt;Azure Static Web Apps&lt;/a&gt;. Yes, I know, I work for Microsoft, so you're probably thinking I would say that regardless. However I really do use what I feel works best for me, and Static Web Apps absolutely fits the bill. It's a wonderful service for hosting full-stack web applications. Static Web Apps uses &lt;a href="https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-39081-chrhar"&gt;Azure Functions&lt;/a&gt; for server-side code, and provides wonderful functionality including &lt;a href="https://docs.microsoft.com/azure/static-web-apps/authentication-authorization"&gt;authentication&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When it comes time to start doing local development, the initial setup can require a couple of steps as there's a fair bit being provided to you by the service. I want to explore how to setup a project for Azure Static Web Apps. I'm going to use &lt;a href="https://svelte.dev"&gt;Svelte&lt;/a&gt;, my current favorite front-end framework, but the steps are similar to any other framework you may choose.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog assumes you have &lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt; and &lt;a href="https://code.visualstudio.com"&gt;Visual Studio Code&lt;/a&gt; already installed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Install Azure Functions Core Tools
&lt;/h2&gt;

&lt;p&gt;Azure Functions is the serverless offering from Azure. By using Azure Functions Core Tools, you can run the service locally on your system for development. The docs show how to &lt;a href="https://www.npmjs.com/package/azure-functions-core-tools"&gt;install Azure Functions Core Tools&lt;/a&gt;. I personally use &lt;a href="https://docs.microsoft.com/windows/wsl/about?WT.mc_id=academic-39081-chrhar"&gt;Windows Subsystem for Linux (WSL)&lt;/a&gt; for all my development. I was able to install by opening a terminal for WSL (Ubuntu in my case) and running the NPM command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; azure-functions-core-tools@3 &lt;span class="nt"&gt;--unsafe-perm&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bootstrap the project
&lt;/h2&gt;

&lt;p&gt;It seems every front-end framework has its own bootstrapping tool. Svelte is no different. To create the project we'll use &lt;a href="https://github.com/Rich-Harris/degit"&gt;degit&lt;/a&gt; and the template provided by Svelte. In a terminal window, execute the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx degit sveltejs/template svelte-static-web-apps
&lt;span class="nb"&gt;cd &lt;/span&gt;svelte-static-web-apps
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the API
&lt;/h2&gt;

&lt;p&gt;With the front-end project created, let's create the back-end. We'll do this by using &lt;code&gt;func&lt;/code&gt;, which is the command-line tool for managing Azure Functions, and was installed with the core tools. The two commands we'll use are &lt;code&gt;func init&lt;/code&gt; to create the project, and &lt;code&gt;func new&lt;/code&gt; to create a new Azure Function. While we won't use the function, I want to at least demo the process.&lt;/p&gt;

&lt;p&gt;Typically, Azure Functions are stored in a folder named &lt;em&gt;api&lt;/em&gt;. To create the folder and project, run the following in the same terminal window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func init api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then select the runtime and language. Choose &lt;em&gt;Node&lt;/em&gt; (option 3) and &lt;em&gt;JavaScript&lt;/em&gt; (option 1).&lt;/p&gt;

&lt;p&gt;To create the first function, run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;api
func new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select &lt;em&gt;HTTP trigger&lt;/em&gt; (option 10) for the template, and specify &lt;em&gt;sample&lt;/em&gt; for the name of the trigger.&lt;/p&gt;

&lt;p&gt;You have now setup Azure Functions for the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Azure Static Web Apps CLI
&lt;/h2&gt;

&lt;p&gt;As highlighted earlier, Static Web Apps includes some neat functionality including authentication. If you are going to develop for the platform you'll very likely want to take advantage of this. In addition, because the server-side is running in Azure Functions, local development can be a little trickier because of how the services will run on your system. Fortunately &lt;a href="https://github.com/Azure/static-web-apps-cli#readme"&gt;Azure Static Web Apps CLI&lt;/a&gt; will manage all of this for us, including giving us a great utility to mock the authentication process.&lt;/p&gt;

&lt;p&gt;You can install it as a dev dependency using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @azure/static-web-apps-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update the start script
&lt;/h2&gt;

&lt;p&gt;Finally we'll need to update the &lt;em&gt;dev&lt;/em&gt; script. Traditionally &lt;em&gt;dev&lt;/em&gt; or &lt;em&gt;start&lt;/em&gt; scripts launch the project for development purposes. We're going to update the &lt;em&gt;dev&lt;/em&gt; script to start everything we need - Svelte's dev server, our Azure Function, and Azure Static Web Apps to tie everything together.&lt;/p&gt;

&lt;p&gt;Open the project directory in Visual Studio Code by returning to the terminal window and running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="c"&gt;# To return to the root folder of the project&lt;/span&gt;
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside Visual Studio Code, open &lt;em&gt;package.json&lt;/em&gt;. Replace the &lt;em&gt;dev&lt;/em&gt; script with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rollup -c -w &amp;amp; swa start http://localhost:5000 --api ./api"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file, and your project is now ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the project
&lt;/h2&gt;

&lt;p&gt;With everything setup, the last thing to do is run the project! Inside of Visual Studio Code, you can open a terminal window by selecting &lt;em&gt;Terminal&lt;/em&gt; &amp;gt; &lt;em&gt;New Terminal&lt;/em&gt;. In the newly opened terminal, run the following to start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;You have now setup a project to use Svelte and Azure Static Web Apps with Azure Functions. If you want to continue to explore, you can see how to &lt;a href="https://docs.microsoft.com/learn/modules/publish-app-service-static-web-app-api/?WT.mc_id=academic-39081-chrhar"&gt;deploy the app&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/learn/modules/publish-static-web-app-authentication/?WT.mc_id=academic-39081-chrhar"&gt;manage authentication&lt;/a&gt;. You can also checkout &lt;a href="https://github.com/GeekTrainer/svelte-static-web-apps?WT.mc_id=academic-39081-chrhar"&gt;the sample&lt;/a&gt; I built while putting together this blog. And of course we're doing plenty of other &lt;a href="https://docs.microsoft.com/javascript/?WT.mc_id=academic-39081-chrhar"&gt;fun stuff with JavaScript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web</category>
      <category>javascript</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Translating text with just a few lines of code using Azure Cognitive Services</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Thu, 19 Nov 2020 21:44:22 +0000</pubDate>
      <link>https://dev.to/azure/translating-text-with-just-a-few-lines-of-code-using-azure-cognitive-services-4fao</link>
      <guid>https://dev.to/azure/translating-text-with-just-a-few-lines-of-code-using-azure-cognitive-services-4fao</guid>
      <description>&lt;p&gt;This article is part of &lt;a href="http://aka.ms/PythonFunBites"&gt;#PythonFunBites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An old co-worker of mine is fond of saying "we're not launching rockets here". The point he was trying to highlight is whatever it is we're doing someone else (and probably somebody much smarter) has already created a solution. I've found this holds true, even in complex spaces like artificial intelligence.&lt;/p&gt;

&lt;p&gt;When we think about some of the problems one would hope to solve with AI we find they're relatively common; there are a lot of people trying to do the same thing. Image recognition. Speech to text. Anomaly detection. All challenges lots of people are looking to AI to resolve.&lt;/p&gt;

&lt;p&gt;So, if there are others doing it, why build something by ourselves? There certainly are instances where a custom model and implementation will be called for. But quite frequently we can use a service created by someone else, someone smarter than we are, whose sole job is to create the best solution possible for the one specific problem.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://docs.microsoft.com/learn/modules/create-manage-cognitive-services/?WT.mc_id=python-10852-chrhar"&gt;Azure Cognitive Services&lt;/a&gt; comes into play. Azure Cognitive Services is a collection of callable AI services which can be incorporated into any application. You can call the services by using SDKs in various languages, or even through REST calls.&lt;/p&gt;

&lt;p&gt;I think a great service to start with is text translation, partly because there's only a handful of lines of code, but also because it's just fun to play with!. I created a video to highlight the service, and how to get started.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/6VXuxIBqV94"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;To use the service you will need an Azure account. Fortunately, if you're using a service like Text Translation, there's a free tier! (Yes, you read that right - free!) I always like to mention if you're a student &lt;a href="https://aka.ms/a4s"&gt;Azure for Students&lt;/a&gt; you can access a bunch of free services and resources as well. You'll notice if you decide to go even further into development you could start to create &lt;a href="https://docs.microsoft.com/learn/modules/create-language-translator-mixed-reality-application-unity-azure-cognitive-services?WT.mc_id=python-10852-chrhar"&gt;Unity applications which include translation services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But text translation is really only the start. There are &lt;a href="https://docs.microsoft.com/azure/cognitive-services?WT.mc_id=python-10852-chrhar"&gt;dozens of services available&lt;/a&gt; for you to play with, almost all of them with a free tier. And the best way to learn is to get in and start playing!&lt;/p&gt;

&lt;p&gt;Watch for content on all things Python at Microsoft between the 16th and 20th of November. Stay tuned here at dev.to for all kinds of content ranging from IoT, to Machine Learning and much more! 🐍&lt;/p&gt;

</description>
      <category>pythonbites</category>
      <category>azure</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>Getting started with web dev using Flask</title>
      <dc:creator>Christopher Harrison</dc:creator>
      <pubDate>Thu, 19 Nov 2020 21:21:52 +0000</pubDate>
      <link>https://dev.to/azure/getting-started-with-web-dev-using-flask-44l5</link>
      <guid>https://dev.to/azure/getting-started-with-web-dev-using-flask-44l5</guid>
      <description>&lt;p&gt;This article is part of &lt;a href="http://aka.ms/PythonFunBites"&gt;#PythonFunBites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's a lot of different web dev frameworks out there, and it can be confusing to figure out which to use when. One of my favorites is &lt;a href="https://flask.palletsprojects.com/"&gt;Flask&lt;/a&gt; because of the fact it mostly gets out of the way, allowing you to do almost whatever you want with it!&lt;/p&gt;

&lt;p&gt;Flask is defined as a "micro-framework", meaning it fills the mandatory requirements of a web framework and not much else. You'll notice Flask has a great routing engine for managing different user requests, a templating engine called &lt;a href="https://jinja.palletsprojects.com/"&gt;Jinja&lt;/a&gt; for rendering HTML on the server, and a couple of other core features. After that, it's really up to us as developers!&lt;/p&gt;

&lt;p&gt;This makes Flask a great choice for creating front-ends for machine learning models you've created or other AI implementations, or scenarios where you have an API already created which needs a user interface. You'll also notice you can get up and running with just a few lines of code.&lt;/p&gt;

&lt;p&gt;I created a video highlighting how to perform the installation and create a &lt;strong&gt;Hello, world&lt;/strong&gt; application using templates.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dKwbCHWuOGI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;It's also worth highlighting the fact &lt;a href="https://code.visualstudio.com/docs/python/tutorial-flask"&gt;Visual Studio Code&lt;/a&gt; makes for a great editor, and you can deploy all these projects to &lt;a href="https://docs.microsoft.com/en-us/azure/developer/python/tutorial-deploy-app-service-on-linux-01?WT.mc_id=python-10852-chrhar"&gt;Azure&lt;/a&gt; if you so desire.&lt;/p&gt;

&lt;p&gt;If you're looking for a lightweight framework on which to build your web applications, Flask can be the perfect option!&lt;/p&gt;

&lt;p&gt;Watch for content on all things Python at Microsoft between the 16th and 20th of November. Stay tuned here at dev.to for all kinds of content ranging from IoT, to Machine Learning and much more! 🐍&lt;/p&gt;

</description>
      <category>pythonfunbites</category>
      <category>python</category>
      <category>flask</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
