<?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: Juan Alejandro Morais</title>
    <description>The latest articles on DEV Community by Juan Alejandro Morais (@timrodz).</description>
    <link>https://dev.to/timrodz</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%2F235832%2F97ae9026-42d7-4100-add1-fb3b058a31dc.jpg</url>
      <title>DEV Community: Juan Alejandro Morais</title>
      <link>https://dev.to/timrodz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/timrodz"/>
    <language>en</language>
    <item>
      <title>Hacktoberfest: How I Bundled &amp; Published A VS Code Extension With Webpack And Azure DevOps</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Tue, 29 Sep 2020 21:46:03 +0000</pubDate>
      <link>https://dev.to/timrodz/hacktoberfest-how-i-bundled-published-a-vs-code-extension-with-webpack-and-azure-devops-blj</link>
      <guid>https://dev.to/timrodz/hacktoberfest-how-i-bundled-published-a-vs-code-extension-with-webpack-and-azure-devops-blj</guid>
      <description>&lt;p&gt;During last year's &lt;a href="https://hacktoberfest.digitalocean.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt;, I decided to make a small, achievable extension for VS Code. It was a good way to learn TypeScript, work with people on Github projects, and most importantly: have fun!&lt;/p&gt;

&lt;p&gt;The extension is called &lt;a href="https://marketplace.visualstudio.com/items?itemName=timrodz.lightswitch" rel="noopener noreferrer"&gt;Light Switch&lt;/a&gt; — It is a time based, light/dark theme switcher. When I published my first series of commits to get started, I also wrote a post about it on DEV. I was sure this would help me get traction and a small following of people that would &lt;em&gt;hopefully&lt;/em&gt; be willing to contribute in one way or another:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/timrodz" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F235832%2F97ae9026-42d7-4100-add1-fb3b058a31dc.jpg" alt="timrodz"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/timrodz/hacktoberfest-let-s-build-a-vs-code-extension-1pn8" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Hacktoberfest: Let's build a VS Code Extension&lt;/h2&gt;
      &lt;h3&gt;Juan Alejandro Morais ・ Oct 16 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#hacktoberfest&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;The post was well-received, and it got the traction I wanted. Once the rush came down, I still needed to figure out how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Create tests.&lt;/li&gt;
&lt;li&gt;
Bundle the extension.&lt;/li&gt;
&lt;li&gt;
Publish the extension.&lt;/li&gt;
&lt;li&gt;
Set up a Continuous Integration (CI) pipline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's how I achieved it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing tests 📝 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you're writing software, writing tests is an awesome way to ensure it will work. Since I did not have much time or experience with TypeScript, I made sure to focus my tests on the theme swapping logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Make sure the themes stay as day/night according to their times&lt;/li&gt;
&lt;li&gt;  Ensure a default "fallback" theme could be chosen if there was an error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since my logic mainly involves time, I focused on time conversions. This is an example of the tests I added:&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;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dayjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;canSwitchToNightTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../util/date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Date Test Suite&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Setting time through the extension&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;00:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canSwitchToNightTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;17:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;23:59&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic assertions, &lt;strong&gt;check!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Bundling the extension! 🚀 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I'm sure many of you have a love/hate relationship with webpack. Yes, it's great, and also painful. Luckily, Microsoft has excellent documentation on &lt;a href="https://code.visualstudio.com/api/working-with-extensions/bundling-extension" rel="noopener noreferrer"&gt;how to bundle a VS Code extension&lt;/a&gt; - yay!&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;1. npm uninstall vscode
2. npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack webpack-cli ts-loader vscode-test
3. npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/vscode@1.37.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Remove the &lt;code&gt;vscode&lt;/code&gt; dependency, as it has been superseded by &lt;code&gt;vscode-test&lt;/code&gt; — This will ensure your tests run on the Azure DevOps pipeline.&lt;/li&gt;
&lt;li&gt;Installed the required basic dependencies&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;@types/vscode@^1.37.0&lt;/code&gt;. Depending on the version of your vscode engine, you will have to specify it as &lt;code&gt;@types/vscode@ENGINE_VERSION&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Removed the &lt;code&gt;postinstall&lt;/code&gt; script of &lt;code&gt;package.json&lt;/code&gt;. It is not needed anymore.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating the Webpack configuration
&lt;/h3&gt;

&lt;p&gt;With this configuration, builds will be (by default) output into the &lt;code&gt;dist/&lt;/code&gt; folder at the root of the project. Nothing too fancy here!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//@ts-check&lt;/span&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/**@type {import('webpack').Configuration}*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/extension.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;extension.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;libraryTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commonjs2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;devtoolModuleFilenameTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../[resource-path]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;devtool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;source-map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;externals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commonjs vscode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;ts$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;use&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="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ts-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adjusting the extension configuration files
&lt;/h3&gt;

&lt;h4&gt;
  
  
  package.json
&lt;/h4&gt;

&lt;p&gt;I added a step called &lt;code&gt;test-compile&lt;/code&gt; so it can compile our source for tests (Read why on the next section)&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;"scripts"&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;"vscode:prepublish"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production &amp;amp;&amp;amp; npm run test-compile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"watch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode development &amp;amp;&amp;amp; tsc -watch -p ./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node ./out/test/runTest.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test-compile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc -p ./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  launch.json
&lt;/h4&gt;

&lt;p&gt;Even though the webpack build points to the &lt;code&gt;dist/&lt;/code&gt; folder, tests are compiled to the &lt;code&gt;out/&lt;/code&gt; folder, which means we have to compile the app (Refer to the &lt;code&gt;test-compile&lt;/code&gt; command of &lt;code&gt;package.json&lt;/code&gt;. Luckily, this can be specified on the &lt;code&gt;preLaunchTask&lt;/code&gt;, so I made sure it ran &lt;code&gt;test-compile&lt;/code&gt;.&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;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="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;"Run Extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outFiles"&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;"${workspaceFolder}/dist/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"preLaunchTask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm: watch"&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;"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;"Extension Tests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outFiles"&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;"${workspaceFolder}/out/test/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"preLaunchTask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm: test-compile"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  .vscodeignore
&lt;/h4&gt;

&lt;p&gt;Getting this one right was a bit difficult, here's why:&lt;/p&gt;

&lt;p&gt;You have to exclude &lt;code&gt;node_modules&lt;/code&gt;. The caveat: If you have a dependency (not devDependency), you will have to include it. I had &lt;code&gt;moment&lt;/code&gt; as a dependency, but was able to swap it for &lt;code&gt;dayjs&lt;/code&gt;, even as a devDependency. &lt;em&gt;Woosh!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a general rule, ignore everything that is not the source of the app (including icons/images your app uses).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# folders
.vscode/**
.vscode-test/**
src
out
node_modules
**/tsconfig.json
**/tslint.json
**/*.map
**/*.ts
*.vsix

# Specific files
.gitignore
webpack.config.js
CONTRIBUTING.md
package-lock.json
.prettierrc

# Special exclusions
images
!images/icon.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Making sure it runs!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I had to make sure my builds were compiling. By running &lt;code&gt;npm run compile&lt;/code&gt; and &lt;code&gt;npm run test-compile&lt;/code&gt;, they succeeded!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Publishing the extension ☁️ &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The only dependency I needed was a global one: &lt;code&gt;npm install -g vsce&lt;/code&gt;. &lt;a href="https://github.com/microsoft/vscode-vsce" rel="noopener noreferrer"&gt;vsce&lt;/a&gt; is a CLI for managing VS Code extensions.&lt;/p&gt;

&lt;p&gt;Interestingly, this was the easiest part. I had to create an Azure DevOps organization, and I followed every step of this &lt;a href="https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/create-organization?view=azure-devops" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When creating the marketplace publisher, I was prompted for my Personal Access Token, which I generated following &lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token" rel="noopener noreferrer"&gt;these steps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My strategy for publishing would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Publish it first using &lt;code&gt;vsce publish&lt;/code&gt; so the app was live&lt;/li&gt;
&lt;li&gt;Set-up a Continuous Integration environment to automate the following deploys.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Making sure it runs!
&lt;/h3&gt;

&lt;p&gt;The cool thing of all this, you can install your builds locally! This is different to debugging your build directly from the &lt;strong&gt;Launch&lt;/strong&gt; menu because it emulates the flow of downloading the build directly from the marketplace.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;vsce package&lt;/code&gt; triggers the &lt;code&gt;vscode:prepublish&lt;/code&gt; script from &lt;code&gt;package.json&lt;/code&gt; configuration. A &lt;code&gt;.vsix&lt;/code&gt; file will be created at the root directory. Install the extension by running &lt;code&gt;code --install-extension extension-name.vsix&lt;/code&gt;. Replace &lt;code&gt;extension-name&lt;/code&gt; for the file generated by &lt;code&gt;vsce package&lt;/code&gt;, i.e. &lt;code&gt;light-switch-0.1.0.vsix&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Continuous Integration (CI) 🛠 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Once my extension was live, I had to implement the most important part: a CI pipeline. This is a great DevOps practice, as it automates all your builds, and runs your tests on new changes - This ensures new code won't break the app before being able to merge it into the master branch.&lt;/p&gt;

&lt;p&gt;You can have a look at my pipeline &lt;a href="https://dev.azure.com/timrodz/Light%20Switch/_build?definitionId=1&amp;amp;_a=summary" rel="noopener noreferrer"&gt;build summary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some key takeaways I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before setting up any CI pipeline, make sure your app works locally, and that every command behaves as intended.&lt;/li&gt;
&lt;li&gt;You don't have to know how to use YAML files to set up a working pipeline. Microsoft offers &lt;a href="https://github.com/microsoft/azure-pipelines-yaml" rel="noopener noreferrer"&gt;many templates to get started with&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Azure DevOps allows you to build and deploy without having to create any artifacts/releases - This is awesome, and it saves a lot of time!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;h2&gt;
  
  
  azure-pipelines.yml
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Builds from every branch, and tag.&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Machines that it builds to&lt;/span&gt;
&lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;linux&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;imageName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ubuntu-16.04'&lt;/span&gt;
    &lt;span class="na"&gt;mac&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;imageName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;macos-10.13'&lt;/span&gt;
    &lt;span class="na"&gt;windows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;imageName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vs2017-win2016'&lt;/span&gt;

&lt;span class="c1"&gt;# Takes in the machines specified in the strategy.&lt;/span&gt;
&lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;vmImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(imageName)&lt;/span&gt;

&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;# Installs Node.js&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodeTool@0&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;versionSpec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;8.x'&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Node.js'&lt;/span&gt;

&lt;span class="c1"&gt;# Installs an X virtual framebuffer (https://en.wikipedia.org/wiki/Xvfb).&lt;/span&gt;
&lt;span class="c1"&gt;# Only required for running the VS Code in the Linux machine.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;/usr/bin/Xvfb :99 -screen 0 1024x768x24 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/span&gt;
      &lt;span class="s"&gt;echo "&amp;gt;&amp;gt;&amp;gt; Started xvfb"&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start xvfb&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;and(succeeded(), eq(variables['Agent.OS'], 'Linux'))&lt;/span&gt;

&lt;span class="c1"&gt;# Run yarn (Install dependencies) and run the compile script.&lt;/span&gt;
&lt;span class="c1"&gt;# It also runs the tests and stops the pipeline if one test fails.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;echo "&amp;gt;&amp;gt;&amp;gt; Compile vscode-test"&lt;/span&gt;
      &lt;span class="s"&gt;yarn &amp;amp;&amp;amp; yarn compile&lt;/span&gt;
      &lt;span class="s"&gt;echo "&amp;gt;&amp;gt;&amp;gt; Run integration test"&lt;/span&gt;
      &lt;span class="s"&gt;yarn &amp;amp;&amp;amp; yarn compile &amp;amp;&amp;amp; yarn test&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DISPLAY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:99.0'&lt;/span&gt;

&lt;span class="c1"&gt;# Publishes the extension to the marketplace.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;echo "&amp;gt;&amp;gt;&amp;gt; Publish"&lt;/span&gt;
      &lt;span class="s"&gt;yarn deploy -p $(VSCODE_MARKETPLACE_TOKEN)&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['Agent.OS'], 'Linux'))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here we have it!&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;The last build had an error while building with Windows, but it was able to deploy the latest changes using the Linux image. See the &lt;a href="https://dev.azure.com/timrodz/Light%20Switch/_build/results?buildId=25&amp;amp;view=results" rel="noopener noreferrer"&gt;build output&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Notes
&lt;/h4&gt;

&lt;p&gt;A YAML configuration can run as many commands as you want. Think of every &lt;code&gt;- bash: |&lt;/code&gt; entry as a set of new commands that will run in a specified batch. It can execute bash commands i.e. &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;The last step, which publishes the extension, passes in a &lt;code&gt;$(VSCODE_MARKETPLACE_TOKEN)&lt;/code&gt; variable. This is the &lt;strong&gt;Personal Access Token (PAT)&lt;/strong&gt; we defined earlier on the Publishing section. If my variable was named &lt;code&gt;secret&lt;/code&gt;, then the script would run &lt;code&gt;yarn deploy -p $(secret)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The last build step has a condition: &lt;code&gt;and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['Agent.OS'], 'Linux'))&lt;/code&gt;. This conditrion tells our pipeline to deploy with builds that meet the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The building machine's OS is Linux (In my case: Ubuntu 16.04).&lt;/li&gt;
&lt;li&gt;The commit has a &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging" rel="noopener noreferrer"&gt;git tag&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;I solved my tagging by using &lt;a href="https://docs.npmjs.com/about-semantic-versioning" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; via &lt;code&gt;npm version&lt;/code&gt; command, i.e. &lt;code&gt;npm version major/minor/patch&lt;/code&gt;. This is convenient because it updates the &lt;code&gt;package.json&lt;/code&gt; version, and makes a commit with a tag:&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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




&lt;h2&gt;
  
  
  It's a wrap! 🌯
&lt;/h2&gt;

&lt;p&gt;The entire process did not take long, but figuring out the CI pipeline was the most complex part by far. Thanks to Microsoft's well-written documentation, I was able to put the pieces together.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://code.visualstudio.com/api/get-started/your-first-extension" rel="noopener noreferrer"&gt;the official guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Share your thoughts!
&lt;/h3&gt;

&lt;p&gt;Have you published a VS Code extension? If so, how was your process? I'd love to learn about your experience!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@chatelp" rel="noopener noreferrer"&gt;Pierre Châtel-Innocenti&lt;/a&gt; on &lt;a href="https://unsplash.com" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>productivity</category>
      <category>typescript</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Creating A Gatsby Portfolio That Shows Your Instagram Posts</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Mon, 02 Mar 2020 23:08:00 +0000</pubDate>
      <link>https://dev.to/timrodz/creating-a-gatsby-portfolio-that-shows-your-instagram-posts-4m24</link>
      <guid>https://dev.to/timrodz/creating-a-gatsby-portfolio-that-shows-your-instagram-posts-4m24</guid>
      <description>&lt;p&gt;I created my first &lt;a href="https://www.gatsbyjs.org/starters/timrodz/gatsby-starter-instagram-baseweb/" rel="noopener noreferrer"&gt;Gatsby Portfolio Starter&lt;/a&gt;. It shows the latest Instagram posts from any user via the Instagram API, and implements &lt;a href="https://baseweb.design" rel="noopener noreferrer"&gt;Base Web&lt;/a&gt;, the Design System built by Uber.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://gatsby-starter-instagram-baseweb.netlify.com/" rel="noopener noreferrer"&gt;Click here for a live demo&lt;/a&gt; 🚀&lt;/p&gt;
&lt;/blockquote&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%2Fi.imgur.com%2FmAi2AXB.jpg" 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%2Fi.imgur.com%2FmAi2AXB.jpg" alt="Screenshot of the gatsby starter with a desktop, tablet and mobile view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, I will show you how I quickly prototyped and built this starter. I will give you tips &amp;amp; tricks, caveats to look for (with their workarounds), and how you can get started with your starter (See what I did there? 👀)&lt;/p&gt;

&lt;p&gt;Click below to see the repository.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/timrodz" rel="noopener noreferrer"&gt;
        timrodz
      &lt;/a&gt; / &lt;a href="https://github.com/timrodz/gatsby-starter-instagram-baseweb" rel="noopener noreferrer"&gt;
        gatsby-starter-instagram-baseweb
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🎢 A lightweight, minimalist Gatsby starter for creating Instagram-based portfolios.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  ❓ What is Gatsby?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; is a free and open-source framework based on React that helps developers build blazing-fast websites and apps. There are lots of &lt;a href="https://www.gatsbyjs.org/plugins/" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; and &lt;a href="https://www.gatsbyjs.org/starters/?v=2" rel="noopener noreferrer"&gt;starters&lt;/a&gt;, which are like themes you can build and hack on top of, and the community is simply amazing — How great!&lt;/p&gt;

&lt;p&gt;I have been toying around with Gatsby for over a month now. I re-designed and re-built &lt;a href="https://www.timrodz.com/" rel="noopener noreferrer"&gt;my portfolio&lt;/a&gt; with it, and I'm also building a portfolio for a friend, who is a freelance photographer. This was the perfect opportunity to dive deep with Gatsby!&lt;/p&gt;

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




&lt;h2&gt;
  
  
  🤔 How does it work?
&lt;/h2&gt;

&lt;p&gt;Creating this starter was unsurprisingly easy - I say this due to nature and learning curve provided by Gatsby. For context, I am a beginner with web technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding the right template
&lt;/h3&gt;

&lt;p&gt;I chose to begin using the &lt;a href="https://www.gatsbyjs.org/starters/gatsbyjs/gatsby-starter-default/" rel="noopener noreferrer"&gt;Gatsby Default Starter&lt;/a&gt;. It's production-ready and is considered the vanilla starter for Gatsby. Great to learn and build upon!&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to Instagram
&lt;/h3&gt;

&lt;p&gt;The main feature of this website is that it can fetch and display Instagram posts. Luckily for me (and you), Gatsby has an &lt;a href="https://www.gatsbyjs.org/packages/gatsby-source-instagram/" rel="noopener noreferrer"&gt;Instagram starter&lt;/a&gt;! It's incredibly easy to set up and offers two ways to get started.&lt;/p&gt;

&lt;h4&gt;
  
  
  Public Scraping
&lt;/h4&gt;

&lt;p&gt;The Instagram API offers an option to scrape up to 12 posts from any public profile. This will be the option we're going to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;allInstaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DESC&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;edges&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;
        &lt;span class="nx"&gt;caption&lt;/span&gt;
        &lt;span class="nx"&gt;localFile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;childImageSharp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;fluid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;GatsbyImageSharpFluid&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;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;h4&gt;
  
  
  Scraping using an API Token
&lt;/h4&gt;

&lt;p&gt;If you want to scrape historical posts (Beyond 12), you will need credentials to authenticate with. Get started &lt;a href="https://www.gatsbyjs.org/packages/gatsby-source-instagram/#instagram-graph-api-token" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This query will show us the latest 12 posts for our Instagram account, along with the &lt;code&gt;id&lt;/code&gt; (Will be used for redirecting to the original post), &lt;code&gt;caption&lt;/code&gt; and &lt;code&gt;localFile&lt;/code&gt;, which contains the data required to show our image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing a design system
&lt;/h3&gt;

&lt;p&gt;After that, I was looking at design systems, because I wanted to &lt;strong&gt;create&lt;/strong&gt; and &lt;strong&gt;iterate&lt;/strong&gt; on a prototype with the least amount of setup. That's when I found &lt;a href="https://baseweb.design" rel="noopener noreferrer"&gt;Base Web&lt;/a&gt;, a design system created by Uber. The lightweight and minimalist approach to design made it perfect for this example.&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Robust components out of the box. From Date Pickers to simple blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.styletron.org" rel="noopener noreferrer"&gt;Styletron&lt;/a&gt; for styling. It uses a CSS-in-JS approach.&lt;/li&gt;
&lt;li&gt;Extensibility through the &lt;a href="https://baseweb.design/guides/understanding-overrides" rel="noopener noreferrer"&gt;Overrides API&lt;/a&gt; and &lt;a href="https://baseweb.design/guides/theming/" rel="noopener noreferrer"&gt;configurable Themes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Built-in Accessibility.&lt;/li&gt;
&lt;li&gt;Great performance thanks to the Styletron engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making responsive elements with BaseWeb is very easy. Here's how you would create a flexible grid that contains and shows images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Gallery&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlexGrid&lt;/span&gt; &lt;span class="nx"&gt;flexGridColumnCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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="nf"&gt;renderImages&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FlexGrid&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see &lt;code&gt;flexGridColumnCount&lt;/code&gt; is surrounded by an array: &lt;code&gt;[1, 2, 3]&lt;/code&gt;. This handles breakpoints automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small screen size: &lt;code&gt;flexGridColumnCount = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Medium screen size: &lt;code&gt;flexGridColumnCount = 2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Large screen size: &lt;code&gt;flexGridColumnCount = 3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Before you start
&lt;/h4&gt;

&lt;p&gt;There is &lt;strong&gt;one caveat&lt;/strong&gt; we will have to get out the way: Gatsby uses &lt;a href="https://www.gatsbyjs.org/docs/react-hydration/" rel="noopener noreferrer"&gt;&lt;strong&gt;hydration&lt;/strong&gt;&lt;/a&gt;, meaning it is Server-Side-Rendered (SSR) to static content with a React runtime. If either code you use, or a plugin access variables such as &lt;code&gt;window&lt;/code&gt; or &lt;code&gt;document&lt;/code&gt;, you will have some trouble when building the app.&lt;/p&gt;

&lt;p&gt;Let's image this is our app's entry point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Styletron&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styletron-engine-atomic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;StyletronProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styletron-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BaseProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baseui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Styletron&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;EntryPoint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StyletronProvider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;engine&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;LightTheme&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/BaseProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyletronProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Looks simple, right? It even works via &lt;code&gt;gatsby develop&lt;/code&gt;. The problem lies when building the app via &lt;code&gt;gatsby build&lt;/code&gt;, as it will throw an error saying &lt;code&gt;document is undefined&lt;/code&gt;, pointing to the &lt;code&gt;styletron-engine-atomic&lt;/code&gt; package. Bummer! Or, is it?&lt;/p&gt;

&lt;p&gt;If you point to the code that is breaking, you will indeed see that &lt;code&gt;styletron-engine-atomic&lt;/code&gt; is accessing the &lt;code&gt;document&lt;/code&gt; element, and this is an important part of understanding Gatsby's ecosystem. These elements &lt;strong&gt;only&lt;/strong&gt; live inside the browser.&lt;/p&gt;

&lt;p&gt;To fix this issue, we can wait until we're in the browser and then load &lt;code&gt;styletron-engine-atomic&lt;/code&gt;. With the magic of &lt;a href="https://reactjs.org/docs/hooks-intro.html" rel="noopener noreferrer"&gt;React hooks&lt;/a&gt; (&lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useState&lt;/code&gt;), we can tell our app to &lt;code&gt;import&lt;/code&gt; the library once the component mounts, meaning we are inside a browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;StyletronProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styletron-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BaseProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baseui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;EntryPoint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEngine&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&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="c1"&gt;// Once the `styletron-engine-atomic` library imports&lt;/span&gt;
    &lt;span class="c1"&gt;// We will grab its content and create a new client through it&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styletron-engine-atomic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;styletron&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientEngine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;styletron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;setEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientEngine&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StyletronProvider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;engine&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;LightTheme&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/BaseProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyletronProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;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;With those changes in mind, this web app is ready to be built.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏋️ Getting Gatsby to do the heavy lifting
&lt;/h2&gt;

&lt;p&gt;An entry point for most Gatsby apps will be the &lt;code&gt;gatsby-config.js&lt;/code&gt; file. You can specify the site metadata and set up your plugins. In this case, I only grabbed a few extra plugins (besides the default ones):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/packages/gatsby-source-instagram/?=source-instagram" rel="noopener noreferrer"&gt;gatsby-source-instagram&lt;/a&gt;: Required to fetch and show data via the Instagram API.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-styletron/?=styletron" rel="noopener noreferrer"&gt;gatsby-plugin-styletron&lt;/a&gt;: Required so Base Web's engine can work along with Styletron and Gatsby. &lt;a href="https://www.styletron.org/getting-started/#with-gatsby" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-alias-imports/" rel="noopener noreferrer"&gt;gatsby-plugin-alias-imports&lt;/a&gt;: Optional but handy tool to create shortcuts for imports, i.e.:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// -- gatsby-config.js&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-alias-imports`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;components&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;__dirname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/components`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/data/`&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="c1"&gt;// -- script.js&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../data/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Converting the app into a PWA (Progressive Web App)
&lt;/h3&gt;

&lt;p&gt;Converting your app into a PWA is the hot thing, and for good reason. Google sums up &lt;a href="https://web.dev/what-are-pwas/" rel="noopener noreferrer"&gt;what PWAs are&lt;/a&gt; pretty well.&lt;/p&gt;

&lt;p&gt;With Gatsby, this is how &lt;em&gt;easy&lt;/em&gt; it was to convert this app into a PWA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable plugin &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-offline/" rel="noopener noreferrer"&gt;gatsby-plugin-offline&lt;/a&gt; inside &lt;code&gt;gatsby-config.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;gatsby-browser.js&lt;/code&gt; file. We will need to add a callback to the &lt;a href="https://www.gatsbyjs.org/docs/browser-apis/#onServiceWorkerUpdateReady" rel="noopener noreferrer"&gt;onServiceWorkerUpdateReady&lt;/a&gt; function which will tell our application's &lt;code&gt;window&lt;/code&gt; to reload.:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onServiceWorkerUpdateReady&lt;/span&gt; &lt;span class="o"&gt;=&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And boom - Once your website is built, you will have the basics of a PWA good to go! Here is the Google &lt;a href="https://developers.google.com/web/tools/lighthouse" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; audit score.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Handling data
&lt;/h3&gt;

&lt;p&gt;To ease things up and keep the most important variables in one place, I created a &lt;code&gt;data/config.js&lt;/code&gt; file. We can add things like the site's title, description, author, social links and other metadata. These variables will also power the &lt;strong&gt;SEO&lt;/strong&gt; component!&lt;/p&gt;

&lt;h4&gt;
  
  
  SEO
&lt;/h4&gt;

&lt;p&gt;I got the idea of using &lt;a href=""&gt;schema.org&lt;/a&gt; organizations from &lt;a href="https://smakosh.com/seo-in-react-apps" rel="noopener noreferrer"&gt;Smakosh&lt;/a&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Thumbnail&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static/images/thumbnail.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;foundingDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;legalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;socialLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structuredDataOrganization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`{
  "@context": "http://schema.org",
  "@type": "Organization",
  "legalName": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;legalName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
  "url": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
  "logo": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
  "foundingDate": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;foundingDate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
  "founders": [{
    "@type": "Person",
    "name": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;legalName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
  }],
  "contactPoint": [{
    "@type": "ContactPoint",
    "email": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
    "contactType": "customer service"
  }],
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;",
    "addressCountry": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
  },
  "sameAs": [
    "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;socialLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instagram&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;socialLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;twitter&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To inject it, Gatsby provides us with a &lt;a href="https://github.com/nfl/react-helmet" rel="noopener noreferrer"&gt;React Helmet&lt;/a&gt; that can be edited. We have to pass the data in the form of an &lt;code&gt;application/ld+json&lt;/code&gt; script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SEO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
    {
      site {
        siteMetadata {
          title
          description
          author
        }
      }
    }
  `&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;metaDescription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Helmet&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/ld+json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;structuredDataOrganization&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Helmet&lt;/span&gt;&lt;span class="err"&gt;&amp;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;h3&gt;
  
  
  Changing the media query breakpoints
&lt;/h3&gt;

&lt;p&gt;It's very simple to override themes with Base Web. Their &lt;a href="https://baseweb.design/blog/responsive-web/#custom-breakpoints" rel="noopener noreferrer"&gt;custom breakpoints example&lt;/a&gt; was all I needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baseui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Specify your custom breakpoint sizes here&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;breakpoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;small&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;769&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;medium&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1216&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;ResponsiveTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaQuery&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`@media screen and (min-width: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;px)`&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;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mediaQuery&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;LightTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ResponsiveTheme&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌯 It's a wrap!
&lt;/h2&gt;

&lt;p&gt;Creating this project was a great way to learn Gatsby and how it works under the hood. It's a Framework that gets comfortable very quickly and allows you to do and focus on creating your web apps. It does this by giving you the tools you need, when you need them, and comes with amazing built-in configurations that are production-ready.&lt;/p&gt;

&lt;p&gt;In terms of Base Web, it's a great design system to build apps and prototypes with, and can easily be overridable. I especially like that it does not have many components that commonly bloat web app - It has the right ones you (and I) probably need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Share your thoughts!
&lt;/h3&gt;

&lt;p&gt;What is your experience with Gatsby? Let me know - I'd love to learn what you have to show and tell!.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@invictar1997?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Soragrit Wongsa&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Get Ready For Global Game Jam With These Free Game Engines</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Wed, 22 Jan 2020 21:35:23 +0000</pubDate>
      <link>https://dev.to/timrodz/get-ready-for-global-game-jam-with-these-free-game-engines-17a1</link>
      <guid>https://dev.to/timrodz/get-ready-for-global-game-jam-with-these-free-game-engines-17a1</guid>
      <description>&lt;p&gt;Hello there! 👋&lt;/p&gt;

&lt;p&gt;Game development is a great way to improve your skills and even try new ones. It involves coding, art, music production, writing, testing, and many more areas! With the rise of its popularity, the number of tutorials and courses have been increasing, and thus decreasing the learning curve for those wanting to get into the industry.&lt;/p&gt;

&lt;p&gt;An amazing way to get into making games is by doing &lt;strong&gt;Game Jams&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a game jam? 💡
&lt;/h2&gt;

&lt;p&gt;Simply put, Game Jams are hackathons where you make games (Board + Digital). Most of the usual hackathon rules apply: you're given a time limit, judges/participants can vote on excellence, and there might even be prizes. The best part though is that you get to work with great people to make awesome games!&lt;/p&gt;

&lt;h3&gt;
  
  
  Great games can come out of game jams! 🚀
&lt;/h3&gt;

&lt;p&gt;This is true! Whether it is &lt;a href="https://globalgamejam.org/" rel="noopener noreferrer"&gt;Global Game Jam&lt;/a&gt;, &lt;a href="http://ldjam.com/" rel="noopener noreferrer"&gt;Ludum Dare&lt;/a&gt;, or even company in-house jams, some amazing games have come out from these!&lt;/p&gt;

&lt;p&gt;Some examples include, but are (definitely) not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://superhotgame.com/play-prototype/" rel="noopener noreferrer"&gt;SUPERHOT&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dinopoloclub.com/games/mini-metro/" rel="noopener noreferrer"&gt;Mini Metro&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://samuraipunk.com/screencheat" rel="noopener noreferrer"&gt;SCREENCHEAT&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keeptalkinggame.com/" rel="noopener noreferrer"&gt;Keep Talking and Nobody Explodes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.surgeonsim.com/" rel="noopener noreferrer"&gt;Surgeon Simulator 2013&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introducing: Global Game Jam 🌎
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1200350981269139456-649" src="https://platform.twitter.com/embed/Tweet.html?id=1200350981269139456"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1200350981269139456-649');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1200350981269139456&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The largest game jam in the world, Global Game Jam (GGJ) started in 2009, and gets bigger by the year! It runs for 48 hours with a global theme. In 2019 alone, GGJ had &lt;strong&gt;860&lt;/strong&gt; locations in &lt;strong&gt;113&lt;/strong&gt; countries create &lt;strong&gt;9,010&lt;/strong&gt; games in &lt;strong&gt;&lt;em&gt;one weekend&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The great news is: you can participate this year!&lt;/p&gt;

&lt;h3&gt;
  
  
  Participating in Global Game Jam 2020 💻
&lt;/h3&gt;

&lt;p&gt;Global Game Jam happens every year — Woohoo! In 2020, it will occur from January 31 to February 2 (Friday to Sunday). To participate, you must:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://globalgamejam.org/2020/jam-sites" rel="noopener noreferrer"&gt;Find A Global Game Jam Site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After you finish registering, carefully read the details of your site. This includes entrance fees (if applicable), food options, age restrictions, etc.&lt;/p&gt;

&lt;p&gt;Once you have read through, make sure you bring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your eager self!&lt;/li&gt;
&lt;li&gt;A spirit of creativity.&lt;/li&gt;
&lt;li&gt;A personal computer (Unless stated otherwise by your site).&lt;/li&gt;
&lt;li&gt;Snacks + Water, or your drink of choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Some sites may lend out computers, paper, pens and other great things to work so you don't have to do this — Check with your site first!&lt;/p&gt;




&lt;h2&gt;
  
  
  Great! Now, how I start making games? 🛠
&lt;/h2&gt;

&lt;p&gt;The following engines have been ordered by personal preference. I will explain their main features, along with download and learning links. The engines will be separated into three areas: &lt;em&gt;Introductory&lt;/em&gt;, &lt;em&gt;Intriguing&lt;/em&gt;, and &lt;em&gt;Challenging&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introductory 🧰
&lt;/h2&gt;

&lt;p&gt;Perfect if you're looking to get started with basic game development. No coding is required, and you get to only focus in the creation of games (No builds or similar hassles).&lt;/p&gt;

&lt;h3&gt;
  
  
  Twine
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx3dzqf6a5g4c8qm7i9vb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx3dzqf6a5g4c8qm7i9vb.png" alt="Twine logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An open-source tool, Twine allows you to create &lt;strong&gt;non-linear, interactive stories&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Free to use &amp;amp; open source!&lt;/li&gt;
&lt;li&gt;Anything you create with it is completely free to use any way you like, including for commercial purposes.&lt;/li&gt;
&lt;li&gt;Publish your game to HTML with a simple click, and receive a shareable link.&lt;/li&gt;
&lt;li&gt;No code required to build a game.&lt;/li&gt;
&lt;li&gt;Add variables, conditional logic, images to your story.&lt;/li&gt;
&lt;li&gt;Tweak the appearance, or add effects with CSS and JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;p&gt;You can find top Twine games on &lt;a href="https://itch.io/games/made-with-twine" rel="noopener noreferrer"&gt;itch.io&lt;/a&gt;. Twine gives developers great creative freedom!&lt;/p&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twinery.org/" rel="noopener noreferrer"&gt;Download Twine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twinery.org/wiki/twine2:guide" rel="noopener noreferrer"&gt;Learn Twine&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/klembot" rel="noopener noreferrer"&gt;
        klembot
      &lt;/a&gt; / &lt;a href="https://github.com/klembot/twinejs" rel="noopener noreferrer"&gt;
        twinejs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Twine, a tool for telling interactive, nonlinear stories
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h3&gt;
  
  
  Bitsy
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1r2n8rwjps5ocrhk8bxl.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1r2n8rwjps5ocrhk8bxl.gif" alt="Bitsy GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bitsy is a small game editor for creating &lt;strong&gt;small, adventurous games&lt;/strong&gt;, created by independent game developer &lt;a href="https://twitter.com/adamledoux" rel="noopener noreferrer"&gt;Adam Le Doux&lt;/a&gt;. It comes with many of the features commonly seen in bigger game engines and is a great starting point to very novice developers wanting to get straight into the (small) action.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Free to use &amp;amp; open source!&lt;/li&gt;
&lt;li&gt;Pure web editor — no installs required.&lt;/li&gt;
&lt;li&gt;Easy import/export of games in HTML format.&lt;/li&gt;
&lt;li&gt;Friendly &amp;amp; open community!&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;p&gt;Check out this list of &lt;a href="https://itch.io/c/201121/bitsy-faves" rel="noopener noreferrer"&gt;Bitsy Faves&lt;/a&gt;. As it's a tiny editor, no &lt;em&gt;notable&lt;/em&gt; games will be out there, at least yet. But if you're in for small indie games, believe me when I say you're in for a treat.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;p&gt;Learning Bitsy is very straightforward. All the information you need to know is inside the engine itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ledoux.itch.io/bitsy" rel="noopener noreferrer"&gt;Download Bitsy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.shimmerwitch.space/bitsyTutorial.html" rel="noopener noreferrer"&gt;Learn Bitsy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/le-doux" rel="noopener noreferrer"&gt;
        le-doux
      &lt;/a&gt; / &lt;a href="https://github.com/le-doux/bitsy" rel="noopener noreferrer"&gt;
        bitsy
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a little engine for little games, worlds, and stories
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  Intriguing 🧪
&lt;/h2&gt;

&lt;p&gt;Independent developers are loving these great, small yet scalable engines. They offer great options for 2D developers (including pixel art) out of the box. Game builds are very light weight and are just right for developers transitioning into more advanced/complex work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Godot
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4c6f0bbchlsqaz7j56vy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4c6f0bbchlsqaz7j56vy.png" alt="Godot logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A new and powerful game engine, Godot is a completely free and open-source engine that powers your games with an incredible set of tools, and removing clutter you (probably) don't need. This is a great engine for those who favour &lt;strong&gt;speed, fast iteration and want a totally free game engine&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Free to use &amp;amp; open source!&lt;/li&gt;
&lt;li&gt;A proactive team that listens to, and engages with the community.&lt;/li&gt;
&lt;li&gt;Supports 2D and 3D graphics out of the box.&lt;/li&gt;
&lt;li&gt;Built-in animator.&lt;/li&gt;
&lt;li&gt;Choose your language: GDScript (like Python), C#, C++, Visual Scripting.&lt;/li&gt;
&lt;li&gt;Cross-Platform build capabilities: Windows, Mac, HTML5, iOS, Android, Xbox, PS4!&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;p&gt;Since it's a relatively new engine, indie games are the norm. You can find the top Godot games on &lt;a href="https://itch.io/games/made-with-godot" rel="noopener noreferrer"&gt;itch.io&lt;/a&gt; and Godot's own &lt;a href="https://godotengine.org/showcase" rel="noopener noreferrer"&gt;Showcase&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://godotengine.org/download" rel="noopener noreferrer"&gt;Download Godot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.godotengine.org/en/3.1/" rel="noopener noreferrer"&gt;Learn Godot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/godotengine" rel="noopener noreferrer"&gt;
        godotengine
      &lt;/a&gt; / &lt;a href="https://github.com/godotengine/godot" rel="noopener noreferrer"&gt;
        godot
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Godot Engine – Multi-platform 2D and 3D game engine
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h3&gt;
  
  
  GameMaker
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdvmqtngb72ulz3vbxpsx.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdvmqtngb72ulz3vbxpsx.jpg" alt="GameMaker 2 logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GameMaker is a great tool for making &lt;strong&gt;2D games&lt;/strong&gt;. With the release of GameMaker 2, they've mastered the beauty and simplicity that the engine offers. It's incredibly popular amongst the 2D developer community, especially with pixel art based games.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;p&gt;For a complete list of features, visit the &lt;a href="https://www.yoyogames.com/gamemaker/features" rel="noopener noreferrer"&gt;Official Site&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free 30-day trial.&lt;/li&gt;
&lt;li&gt;Editor:

&lt;ul&gt;
&lt;li&gt;Room/Level editor.&lt;/li&gt;
&lt;li&gt;Object inheritance.&lt;/li&gt;
&lt;li&gt;Git integration.&lt;/li&gt;
&lt;li&gt;Networking.&lt;/li&gt;
&lt;li&gt;Many, many more!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;An easy to use &lt;em&gt;Drag And Drop&lt;/em&gt; prototyping system.&lt;/li&gt;

&lt;li&gt;Built-in programming language: GML — Based on C, but a lot easier to use.&lt;/li&gt;

&lt;li&gt;Cross-Platform build capabilities: Windows, Mac, HTML5, iOS, Android, Xbox, PS4!&lt;/li&gt;

&lt;li&gt;Lots of online resources to learn from, ranging from specific tutorials to complete courses.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/showcase/13/hyper-light-drifter" rel="noopener noreferrer"&gt;Hyper Light Drifter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/showcase/276/minit" rel="noopener noreferrer"&gt;Minit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/showcase/219/nidhogg-2" rel="noopener noreferrer"&gt;Nidhogg 2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/showcase/218/nuclear-throne" rel="noopener noreferrer"&gt;Nuclear Throne&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;p&gt;GameMaker was one of the first engines I used. It's great for getting started in game development, while also being great to stick with!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/get" rel="noopener noreferrer"&gt;Download GameMaker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.yoyogames.com/learn" rel="noopener noreferrer"&gt;Learn GameMaker&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Challenging ⚗️
&lt;/h2&gt;

&lt;p&gt;From independents to giants, these engines are shaping the world of game development. They offer vast amounts of learning resources, a plethora of free &amp;amp; paid assets, affordable pricing options, and powerful features out of the box. You can modify them to your will and game's needs, implement advanced &lt;/p&gt;

&lt;h3&gt;
  
  
  Unity
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fue798uizax7uzhjwxkuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fue798uizax7uzhjwxkuw.png" alt="Unity logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unity has been gaining popularity at increasing speeds, and a favourite among &lt;strong&gt;mobile developers&lt;/strong&gt;. With a team full of passionate developers, they've been working with the community in many awesome ways! It's the preferred tool for many small- to mid-sized indies and even some AAA. Unity offers great scalability without compromising essential tools of the trade.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Free to use &amp;amp; publish with. Pay only if you want, or if your game brings over $100K in revenue.&lt;/li&gt;
&lt;li&gt;Built-in animator.&lt;/li&gt;
&lt;li&gt;Hackable/extendable editor.&lt;/li&gt;
&lt;li&gt;Code with the powerful C# language. No need to compile assets to run — Script changes can take as little as seconds before you can continue testing.&lt;/li&gt;
&lt;li&gt;Native 3D support — The team is working on improving the 2D tools.&lt;/li&gt;
&lt;li&gt;Asset store full of useful tools, art, starters, and more!&lt;/li&gt;
&lt;li&gt;Cross-Platform build capabilities: Windows, Mac, HTML5, iOS, Android, Xbox, PS4!&lt;/li&gt;
&lt;li&gt;Lots of online resources to learn from, ranging from specific tutorials to complete courses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.monumentvalleygame.com/mv2" rel="noopener noreferrer"&gt;Monument Valley 1 &amp;amp; 2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mobiusdigitalgames.com/outer-wilds.html" rel="noopener noreferrer"&gt;Outer Wilds&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.callofduty.com/mobile" rel="noopener noreferrer"&gt;Call Of Duty Mobile&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.ghosttowngames.com/overcooked/" rel="noopener noreferrer"&gt;Overcooked 1 &amp;amp; 2&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://store.unity.com/download-nuo" rel="noopener noreferrer"&gt;Download Unity&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unity.com/learn" rel="noopener noreferrer"&gt;Learn Unity&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I have used Unity both personally and professionally during my game development career. It is currently my preferred engine. Therefore, my opinion may be biased!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Unreal Engine
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpduhe1adi5lz1g03o3cm.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpduhe1adi5lz1g03o3cm.jpg" alt="Unreal Engine logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unreal Engine is one of the biggest players out there, especializing in creating &lt;strong&gt;AAA quality&lt;/strong&gt; titles. Ever since releasing Fortnite, they've grown, A LOT! From CGI to art showcases, to high fidelity games, and even mobile games, they have you covered. An engine that is favoured amongst mid- to large-size teams, and many AAA studios, UE is an amazing tool.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Free to use &amp;amp; publish with. It can be free of cost if your game revenue is less than $3,000 /quarter; if more, 5% of your game’s gross revenue will be charged.&lt;/li&gt;
&lt;li&gt;Hackable/extendable editor - You can fork UE4 on &lt;a href="https://www.unrealengine.com/en-US/ue4-on-github" rel="noopener noreferrer"&gt;Github&lt;/a&gt;!.&lt;/li&gt;
&lt;li&gt;Use Visual Scripting (Blueprints) or C++ to power your game, and take full control of the logic.&lt;/li&gt;
&lt;li&gt;Great starter packs straight out of the box.&lt;/li&gt;
&lt;li&gt;Asset store full of useful tools, art, starters, and more!&lt;/li&gt;
&lt;li&gt;Cross-Platform build capabilities: Windows, Mac, HTML5, iOS, Android, Xbox, PS4!&lt;/li&gt;
&lt;li&gt;Lots of online resources to learn from, ranging from specific tutorials to complete courses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Notable Games
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.epicgames.com/fortnite/en-US/home" rel="noopener noreferrer"&gt;Fortnite&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://outerworlds.obsidian.net/en" rel="noopener noreferrer"&gt;Outer Worlds&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://borderlands.com/en-US/" rel="noopener noreferrer"&gt;Borderlands 3&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ashen-game.com/" rel="noopener noreferrer"&gt;Ashen&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;p&gt;Note: You will have to create an Epic account to use Unreal Engine's tools. The good thing is that if you already play any of their games, or use their store, you'll have an account ready to go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.unrealengine.com/en-US/download" rel="noopener noreferrer"&gt;Download Unreal Engine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.unrealengine.com/en-US/onlinelearning" rel="noopener noreferrer"&gt;Learn Unreal Engine&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Honorable Mentions 🌞
&lt;/h2&gt;

&lt;p&gt;There are lots of great game engines! Since one post cannot cover them all without getting too big, here are some options worth thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://phaser.io/" rel="noopener noreferrer"&gt;Phaser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.lexaloffle.com/pico-8.php" rel="noopener noreferrer"&gt;PICO-8&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://love2d.org/" rel="noopener noreferrer"&gt;LÖVE2D&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gbstudio.dev/" rel="noopener noreferrer"&gt;GB Studio&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/lumberyard/" rel="noopener noreferrer"&gt;Amazon Lumberyard&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Moving Forward 🎮
&lt;/h2&gt;

&lt;p&gt;This is only the start of game development. After you get familiarised with a tool, make sure you &lt;strong&gt;set a small, achievable goal&lt;/strong&gt;. The games industry is growing with a speed so incredible, there's no better time to jump on in! You're all welcome to join this incredible journey.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/dWYU3i-mqEo" rel="noopener noreferrer"&gt;Annie Spratt&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Hacktoberfest: From Decision To Completion</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Mon, 21 Oct 2019 00:24:08 +0000</pubDate>
      <link>https://dev.to/timrodz/hacktoberfest-from-decision-to-completion-3ogb</link>
      <guid>https://dev.to/timrodz/hacktoberfest-from-decision-to-completion-3ogb</guid>
      <description>&lt;p&gt;¡Hola/Hello/Kia Ora everyone! 👋&lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Making A Decision &amp;amp; Sticking To It 🚀&lt;/li&gt;
&lt;li&gt;Tackling The Challenge 👨🏽‍💻&lt;/li&gt;
&lt;li&gt;
Exploring The Web! 🌐

&lt;ul&gt;
&lt;li&gt;DEV&lt;/li&gt;
&lt;li&gt;DeckDeckGo&lt;/li&gt;
&lt;li&gt;Making A VS Code Extension&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lessons Learned, A Retrospective ❤️&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;I'm always looking for ways to learn and improve who I am, personally and career-wise. This year I completed my first ever Hacktoberfest — It felt great! Now that I've completed it and have stayed active with contributions, I wonder: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What &lt;strong&gt;inspired&lt;/strong&gt; me? &lt;/li&gt;
&lt;li&gt;How can I stay &lt;strong&gt;motivated&lt;/strong&gt; to work on more open source projects?&lt;/li&gt;
&lt;li&gt;How can I &lt;strong&gt;encourage&lt;/strong&gt; others to do the same?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dx2wvo7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/14bbn7cgrbgxtzu3n2zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dx2wvo7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/14bbn7cgrbgxtzu3n2zy.png" alt="Hacktoberfest pull request status"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Making A Decision &amp;amp; Sticking To It 🚀 &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;This year I made the switch from game programming to Full-stack. Before the switch, I had only been coding in languages such as &lt;code&gt;C++&lt;/code&gt;, &lt;code&gt;C#&lt;/code&gt;, &lt;code&gt;Lua&lt;/code&gt;, and using game engines such as &lt;code&gt;Unreal Engine 4&lt;/code&gt; and &lt;code&gt;Unity3D&lt;/code&gt;. I've been discovering and working with technologies like &lt;code&gt;JavaScript&lt;/code&gt;, &lt;code&gt;Python&lt;/code&gt;, and &lt;code&gt;SQL&lt;/code&gt; to name a few. The breadth of tools, frameworks, libraries, APIs out there are tremendous - I can get why it might be so hard to get into this!&lt;/p&gt;

&lt;h3&gt;
  
  
  Impostor Syndrome Kicks In
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alright, I know how to code. Or do I? Surely I can work on a small issue and solve it, right? How about data structures? I've forgotten to implement a &lt;code&gt;B-Tree&lt;/code&gt; yet again...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Impostor Syndrome accompanies those who work or have worked in the Games Industry, and it has decided to stay. To prove myself that I am a capable programmer (and more importantly, that I'm more than willing to overcome obstacles), I started creating side-projects to work on.&lt;/p&gt;

&lt;p&gt;But if you're like me, you tend to come up with lots of side-projects, only to never work on them again. And that's fine - Some of these projects have a specific purpose, and they may have taught you the thing you wanted to know. Time to move on!&lt;/p&gt;

&lt;p&gt;Since I'm also now working on web technologies, I wanted to expand portfolio with projects that were more relevant to my job - All I had were games and a couple of websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Open Source Helped
&lt;/h3&gt;

&lt;p&gt;I was looking for a way to publish an old blog post I wrote on my website - First I tried Medium, but I generally dislike Medium. It feels like it was &lt;a href="https://dev.to/devteam/medium-was-never-meant-to-be-a-part-of-the-developer-ecosystem-25a0"&gt;not meant for developers&lt;/a&gt;. That lead me to discover DEV, and with it, a post talking about Hacktoberfest — I was sold immediately after!&lt;/p&gt;

&lt;p&gt;When I discovered Open Source, I noticed the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An infinite amount of &lt;strong&gt;projects&lt;/strong&gt; to work on. If I can't do one, I might simply jump onto another - Great for someone like myself.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;community&lt;/strong&gt; of passionate, friendly developers collaborating and communicating together.&lt;/li&gt;
&lt;li&gt;Barriers ranging from short to very tall - There are issues for those with &lt;strong&gt;any level of experience&lt;/strong&gt;. &lt;em&gt;Woohoo!&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;"Remote Work" vibes, where the maintainers of a project act as project leads. They ensure collaborators stay in tune with the project's vision and are &lt;strong&gt;happy to help&lt;/strong&gt; out.
I was convinced. Time to give this a try! Working on multiple ones would keep my mind agile, constantly looking at new horizons.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Tackling The Challenge 👨🏽‍💻 &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;With any kind of programming task, I focus on creating an MVP (Minimum Viable Product) first —You don't learn variables and start writing classes right away— Instead, I ask myself questions i.e.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are the requirements needed to complete this task?&lt;/li&gt;
&lt;li&gt;Do I need to create a complex input handler this early?&lt;/li&gt;
&lt;li&gt;Have I made a plan on how to tackle this? Flow Charts, UML Diagrams, Notes, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were the steps I followed to complete my first Hacktoberfest:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Learning How Open Source Actually Works
&lt;/h3&gt;

&lt;p&gt;Projects like &lt;a href="https://github.com/firstcontributions/first-contributions"&gt;First Contributions&lt;/a&gt; and Hacktoberfest's &lt;a href="https://hacktoberfest.digitalocean.com/details"&gt;Getting Started&lt;/a&gt; guide are great for newcomers like me. They teach you the basics of open source, where to find projects, and best practices.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note on commit signature verification:&lt;br&gt;
Some projects will require you to verify your commits. This means you will have to create and register a GPG signature (I had to do this). Learn more: &lt;a href="https://help.github.com/en/articles/about-commit-signature-verification"&gt;GitHub Signature Verification&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Working with &lt;code&gt;Markdown&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Spanish is my first language, so I decided to put my translation skills to test. For this PR, I found this project and added a Spanish version:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/lucasgdb/useful-dev-tools/pull/6"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add Spanish (LatAm) version
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#6&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/lucasgdb/useful-dev-tools/pull/6"&gt;&lt;time&gt;Sep 30, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Added a spanish version of this repository.&lt;/p&gt;
&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Changes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;All files now present their alternative language versions inside a &lt;code&gt;list&lt;/code&gt; element.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lucasgdb/useful-dev-tools/pull/6"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  3. Working With &lt;code&gt;HTML&lt;/code&gt;, &lt;code&gt;CSS&lt;/code&gt; &amp;amp; &lt;code&gt;JavaScript&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;HTML&lt;/code&gt; and &lt;code&gt;CSS&lt;/code&gt; are great programming languages for beginners. They provide us with beautiful sites and power the web.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/brittanyrw/emojiscreen/pull/399"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add EmojiPages link to footer
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#399&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/brittanyrw/emojiscreen/pull/399"&gt;&lt;time&gt;Sep 30, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      
&lt;ul&gt;
&lt;li&gt;[x] 🔍 I have searched the &lt;code&gt;data.js&lt;/code&gt; file and confirmed I am not adding a duplicate entry. Note: Different versions of the same show/movie are okay to add such as Lion King (1994) and Lion King (2019) or Rent (movie) and Rent (musical).&lt;/li&gt;
&lt;li&gt;[x] 🌈 I have added a single year under &lt;code&gt;year&lt;/code&gt;. Note: Do not add ranges such as 2017-2019.&lt;/li&gt;
&lt;li&gt;[x] 📅 I have added a type from one of the following: &lt;code&gt;movie&lt;/code&gt; , &lt;code&gt;tv&lt;/code&gt; or &lt;code&gt;musical&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 🔗 I have added the IMDB page or Playbill archive page under &lt;code&gt;itemLink&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 3️⃣ I have at least three emojis listed under &lt;code&gt;emojiImgs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 5️⃣ I have a maximum of five emojis listed under &lt;code&gt;emojiImgs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 👍 My pull request has a descriptive title (such as &lt;code&gt;Added The Lion King&lt;/code&gt; or &lt;code&gt;Added Black Panther, The Avengers: Endgame and Thor&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[x] ⭐ My genres are all inside of square brackets &lt;code&gt;[ ]&lt;/code&gt; and each are individually wrapped in quotation marks and have a comma between each one. (such as submitting this &lt;code&gt;"genres": ["adventure","mystery","animation"]&lt;/code&gt; and not this &lt;code&gt;"genres":["adventure, mystery, animation"]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[x] 🖍️ I have placed the new show(s) or movie(s) in alphabetical order based on title. If the show or movie starts with 'the', then use the second word to alphabetize.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Changes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I wrapped both footer links inside a list.&lt;/li&gt;
&lt;li&gt;If we get more projects, we can simply add a new &lt;code&gt;li&lt;/code&gt; object, and they'll be evenly spaced between themselves.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Closes #294&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/brittanyrw/emojiscreen/pull/399"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;JavaScript&lt;/code&gt; empowers our web, granting it the ability to do amazing things! I went for basic concepts: Working with an &lt;code&gt;object&lt;/code&gt; and editing text inside it.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/brittanyrw/emojiscreen/pull/400"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add emojiImgs to 'On The Town' and 'RocketMan'
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#400&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/brittanyrw/emojiscreen/pull/400"&gt;&lt;time&gt;Sep 30, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      
&lt;ul&gt;
&lt;li&gt;[x] 🔍 I have searched the &lt;code&gt;data.js&lt;/code&gt; file and confirmed I am not adding a duplicate entry. Note: Different versions of the same show/movie are okay to add such as Lion King (1994) and Lion King (2019) or Rent (movie) and Rent (musical).&lt;/li&gt;
&lt;li&gt;[x] 🌈 I have added a single year under &lt;code&gt;year&lt;/code&gt;. Note: Do not add ranges such as 2017-2019.&lt;/li&gt;
&lt;li&gt;[x] 📅 I have added a type from one of the following: &lt;code&gt;movie&lt;/code&gt; , &lt;code&gt;tv&lt;/code&gt; or &lt;code&gt;musical&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 🔗 I have added the IMDB page or Playbill archive page under &lt;code&gt;itemLink&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 3️⃣ I have at least three emojis listed under &lt;code&gt;emojiImgs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 5️⃣ I have a maximum of five emojis listed under &lt;code&gt;emojiImgs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[x] 👍 My pull request has a descriptive title (such as &lt;code&gt;Added The Lion King&lt;/code&gt; or &lt;code&gt;Added Black Panther, The Avengers: Endgame and Thor&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[x] ⭐ My genres are all inside of square brackets &lt;code&gt;[ ]&lt;/code&gt; and each are individually wrapped in quotation marks and have a comma between each one. (such as submitting this &lt;code&gt;"genres": ["adventure","mystery","animation"]&lt;/code&gt; and not this &lt;code&gt;"genres":["adventure, mystery, animation"]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[x] 🖍️ I have placed the new show(s) or movie(s) in alphabetical order based on title. If the show or movie starts with 'the', then use the second word to alphabetize.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Changes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I added an extra emoji to the following entries (Which had 2 emojis each):
&lt;ul&gt;
&lt;li&gt;On The Town&lt;/li&gt;
&lt;li&gt;RocketMan&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's also worth noting that certain Emoji combinations won't play properly with JSON. This might be worth investigating further, as I can see emojis work as complex strings that get encoded with different rules (e.g. 💩 will be encoded differently than 👯‍♀️, and their string lengths will vary)&lt;/p&gt;


&lt;p&gt;Closes #79&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/brittanyrw/emojiscreen/pull/400"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Learning By Example; Developing A Habit
&lt;/h3&gt;

&lt;p&gt;After finishing these tasks, I felt confident enough to tackle more difficult ones. I decided to work on codebases with unfamiliar technologies. It was time to explore the web!&lt;/p&gt;




&lt;h1&gt;
  
  
  Exploring The Web! 🌐 &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;After finishing these basic tasks, I felt confident enough to tackle more difficult ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌈 DEV &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To begin, I decided to work on DEV, as I'm loving this site! It was my first time trying &lt;code&gt;Ruby&lt;/code&gt;, so you can imagine the confusion I had with the syntax. DEV's codebase is huge, so I wanted to make changes that I knew weren't going to destroy the site. I approached this with the following mindset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn basic Ruby: &lt;a href="https://www.tutorialspoint.com/ruby/ruby_syntax.htm"&gt;TutorialsPoint&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Find out how the Ruby ecosystem works. This article from &lt;a href="https://www.stuartellis.name/articles/erb/"&gt;stuartellis&lt;/a&gt; helped me understand the basics of &lt;em&gt;Embedded Ruby Templating&lt;/em&gt; (ERB)&lt;/li&gt;
&lt;li&gt;Hack code around and see what the output gives&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/thepracticaldev/dev.to/pull/4137"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Improve the tag edit page (Tag moderators only)
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#4137&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/thepracticaldev/dev.to/pull/4137"&gt;&lt;time&gt;Sep 30, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      

&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;What type of PR is this? (check all applicable)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[ ] Refactor&lt;/li&gt;
&lt;li&gt;[x] Feature&lt;/li&gt;
&lt;li&gt;[ ] Bug Fix&lt;/li&gt;
&lt;li&gt;[ ] Documentation Update&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Description&lt;/h2&gt;
&lt;p&gt;Since it's my first time working with Ruby, I decided to learn about ERB and do minor yet pleasing styling changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decreased indentation for tag-edit.scss&lt;/li&gt;
&lt;li&gt;Imported variables &amp;amp; mixins for code standardisation.&lt;/li&gt;
&lt;li&gt;Moved the section order around to show mainly used ones first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Textarea&lt;/code&gt; resizing is restricted to vertical&lt;/li&gt;
&lt;li&gt;Focusing on a text field will set the border to a different colour&lt;/li&gt;
&lt;li&gt;The 'Save Changes' CTA has been changed to go in accord with DEV's aesthetic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Related Tickets &amp;amp; Documents&lt;/h2&gt;
&lt;p&gt;Improve the tag edit pages #3953&lt;/p&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Mobile &amp;amp; Desktop Screenshots/Recordings (if there are UI changes)&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/7434353/65873821-9f853f00-e3e0-11e9-9aba-ae3663fe5da5.png" rel="nofollow"&gt;&lt;img width="839" alt="Screen Shot 2019-10-01 at 12 15 37 AM" src="https://res.cloudinary.com/practicaldev/image/fetch/s--CqvxZxQm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/7434353/65873821-9f853f00-e3e0-11e9-9aba-ae3663fe5da5.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Added to documentation?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[ ] docs.dev.to&lt;/li&gt;
&lt;li&gt;[ ] readme&lt;/li&gt;
&lt;li&gt;[x] no documentation needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;[optional] What gif best describes this PR or how it makes you feel?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/204b7c25b527f59f6082f45b3e3b98eb930fc11f/68747470733a2f2f6d65646961322e67697068792e636f6d2f6d656469612f33316c5076354c3361497654692f67697068792e6769663f6369643d373930623736313131656632356361336239636232343233616263373662343439383933616230623237653832636566267269643d67697068792e676966" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/204b7c25b527f59f6082f45b3e3b98eb930fc11f/68747470733a2f2f6d65646961322e67697068792e636f6d2f6d656469612f33316c5076354c3361497654692f67697068792e6769663f6369643d373930623736313131656632356361336239636232343233616263373662343439383933616230623237653832636566267269643d67697068792e676966" alt="alt_text"&gt;&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thepracticaldev/dev.to/pull/4137"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Plus: Contributing to DEV gives you a cool badge!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3SfPTWOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dwyvrlntc1ddtc7q4slp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3SfPTWOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dwyvrlntc1ddtc7q4slp.png" alt="DEV Contributor Badge"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Contribute to DEV&lt;/strong&gt;: &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ben" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bgwIhvJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--1M1qt9Sp--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/1/f451a206-11c8-4e3d-8936-143d0a7e65bb.png" alt="ben image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/devteam/how-to-contribute-to-dev-this-hacktoberfest-5b91" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to contribute to DEV this hacktoberfest&lt;/h2&gt;
      &lt;h3&gt;Ben Halpern ・ Oct 1 '19 ・ 6 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#hacktoberfest&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#contributorswanted&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  📊 DeckDeckGo &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://deckdeckgo.com/"&gt;DeckDeckGo&lt;/a&gt; is an open-source presentation editor - And a very powerful one! It was also my first time using &lt;code&gt;StencilJS&lt;/code&gt;. This was my approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn the core concepts for Stencil JS: &lt;a href="https://stenciljs.com/docs/introduction"&gt;Stencil Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ask proactive questions to the project maintainer (lead):

&lt;ul&gt;
&lt;li&gt;What do they expect from a hypothetical PR? i.e. Acceptance Criteria&lt;/li&gt;
&lt;li&gt;Ask questions on how to approach the PR&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Ask what the project structure is. How do files talk to each other? I find this helped me understand the code more than anything for this case!&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/deckgo/deckdeckgo/pull/406"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add basic vertical split functionality
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#406&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/deckgo/deckdeckgo/pull/406"&gt;&lt;time&gt;Oct 13, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add Prop() &lt;code&gt;vertical&lt;/code&gt; to DeckdeckgoSlideSplit&lt;/li&gt;
&lt;li&gt;Append attribute &lt;code&gt;-vertical&lt;/code&gt; to slide classes &lt;code&gt;deckgo-slide&lt;/code&gt; and &lt;code&gt;deckgo-slide-split&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add and extend &lt;code&gt;deckgo-slide-vertical&lt;/code&gt; and &lt;code&gt;deckgo-slide-split-vertical&lt;/code&gt; styles:
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;deckgo-slide-vertical&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;flex-flow is &lt;code&gt;column wrap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;height is slide height - bottom paddings * 2: &lt;code&gt;calc(var(--slide-height) - (2 * var(--slide-split-padding-bottom, var(--slide-padding-bottom-default))))&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deckgo-slide-split-vertical&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;width is slide width - end &amp;amp; start paddings: &lt;code&gt;calc(var(--slide-width) - (var(--slide-split-padding-end, var(--slide-padding-end-default))) - (var(--slide-split-padding-start, var(--slide-padding-start-default))));&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Closes #372 🚀&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/deckgo/deckdeckgo/pull/406"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Learn more about DeckDeckGo&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/daviddalbusco" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Suapzhpj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--V6snj1kF--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/131563/0e6ac862-e699-4dcc-b34a-542628af779e.jpg" alt="daviddalbusco image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/daviddalbusco/we-are-developing-an-open-source-editor-for-presentations-1bng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;We are developing an open source editor for presentations&lt;/h2&gt;
      &lt;h3&gt;David Dal Busco ・ Apr 29 '19 ・ 5 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#motivation&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  🛠 Making A VS Code Extension &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I started &lt;a href="https://github.com/timrodz/vscode-light_switch"&gt;LightSwitch&lt;/a&gt; a couple of weeks ago. I decided to write a DEV post about it:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/timrodz" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dc216rrt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--tvAyghjG--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/235832/97ae9026-42d7-4100-add1-fb3b058a31dc.jpg" alt="timrodz image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/timrodz/hacktoberfest-let-s-build-a-vs-code-extension-1pn8" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Hacktoberfest: Let's build a VS Code Extension&lt;/h2&gt;
      &lt;h3&gt;Juan Alejandro Morais ・ Oct 16 '19 ・ 2 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#hacktoberfest&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Turns out, it was a success! I started by creating my own issues (After having implemented and pushed the MVP out), adding labels such as &lt;code&gt;hacktoberfest&lt;/code&gt;, &lt;code&gt;help wanted&lt;/code&gt;, &lt;code&gt;good first issue&lt;/code&gt; — Last thing I knew, awesome folks were contributing to the project! ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn more about Light Switch&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        timrodz
      &lt;/a&gt; / &lt;a href="https://github.com/timrodz/vscode-light-switch"&gt;
        vscode-light-switch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
       💡 Light Switch allows you to set-up two themes that swap around day &amp;amp; night. All you have to do is pick your themes and set your preferred times.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h1&gt;
  
  
  Lessons Learned, A Retrospective ❤️ &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Working with Open Source software has taught me how to become a better developer, and how to approach problems through a new lens. I have actioned my learning into the following areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Communication

&lt;ul&gt;
&lt;li&gt;Writing commit messages and summaries that are more &lt;strong&gt;descriptive and contextual&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Focusing on words that can express your thoughts &lt;strong&gt;clearly&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Asking better, smaller questions and being open to &lt;strong&gt;clarify&lt;/strong&gt; them.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Learning new technologies:

&lt;ul&gt;
&lt;li&gt;Web technologies, as complex as they may seem, &lt;strong&gt;don't have to be&lt;/strong&gt;. Try different approaches like toying with code, watching tutorials, taking a course, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;There are many ways to solve a problem - have an &lt;strong&gt;open mind&lt;/strong&gt; when working with Open Source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  If you're still in doubt...
&lt;/h3&gt;

&lt;p&gt;...We all are at some point, no matter how experienced some may seem! Getting into Open Source can seem daunting, especially if you're just getting started with tech. The first steps are the hardest to give - &lt;strong&gt;Start small, grow big&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@tateisimikito?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jukan Tateisi&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Hacktoberfest: Let's build a VS Code Extension</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Wed, 16 Oct 2019 20:14:37 +0000</pubDate>
      <link>https://dev.to/timrodz/hacktoberfest-let-s-build-a-vs-code-extension-1pn8</link>
      <guid>https://dev.to/timrodz/hacktoberfest-let-s-build-a-vs-code-extension-1pn8</guid>
      <description>&lt;p&gt;Hi everyone! 👋&lt;/p&gt;

&lt;p&gt;A few weeks ago, I started building a VS Code extension called &lt;a href="https://github.com/timrodz/vscode-light_switch"&gt;LightSwitch&lt;/a&gt;. It allows you to set-up two themes that swap around day &amp;amp; night. All you have to do is choose your themes and set your preferred times to switch them.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        timrodz
      &lt;/a&gt; / &lt;a href="https://github.com/timrodz/vscode-light-switch"&gt;
        vscode-light-switch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
       💡 Light Switch allows you to set-up two themes that swap around day &amp;amp; night. All you have to do is pick your themes and set your preferred times.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Update: thanks for all the support! I appreciate you all. ❤️&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Any stars are more than welcome ⭐&lt;/p&gt;

&lt;p&gt;Since we're in Hacktoberfest, building a tool together would be a great way to celebrate it (along with open source software)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why? 🤔
&lt;/h2&gt;

&lt;p&gt;Not so long ago, I started wearing prescription glasses, and thus I have been swapping between light/dark themes according to where/when I'm working.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Why not make a tool to automate this?!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was the perfect reason to work on a small project that would teach me the API, workflows of VS Code, along with Typescript.&lt;/p&gt;

&lt;p&gt;I must admit, creating an MVP was incredibly easy, and I encourage all fellow devs to &lt;a href="https://code.visualstudio.com/api/get-started/your-first-extension"&gt;tinker with their own extensions&lt;/a&gt; — It's also a great way to get started with Typescript!&lt;/p&gt;

&lt;h2&gt;
  
  
  The extension 🚀
&lt;/h2&gt;

&lt;p&gt;A basic implementation of LightSwitch is working, with the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set themes to night and day&lt;/li&gt;
&lt;li&gt;Switch between night/day themes&lt;/li&gt;
&lt;li&gt;Switch themes according to a specific time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By collaborating in this project you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Typescript to implement features, tests and fix bugs. Don't know the language? No worries! You can &lt;a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html"&gt;learn Typescript in 5 minutes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Be exposed to API methods that will help you understand how extensions work. Discover the &lt;a href="https://code.visualstudio.com/api/references/vscode-api"&gt;VS Code API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Achieve your Hacktoberfest PRs (In case you need them).&lt;/li&gt;
&lt;li&gt;Work on a small Open Source project!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I' open to discussions of any kind. Any contribution is more than valid ❤&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm in! Show me the issues 🛠
&lt;/h2&gt;

&lt;p&gt;Woop Woop! The complete list of issues can be found &lt;a href="https://github.com/timrodz/vscode-light_switch/issues"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/12"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Discussion: Features &amp;amp; Enhancements
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#12&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/12"&gt;&lt;time&gt;Oct 17, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hi team!&lt;/p&gt;
&lt;p&gt;If you have any features/enhancements you'd like to propose, this is the place to share them.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/timrodz/vscode-light-switch/issues/12"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/4"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add better screenshots / GIFs
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#4&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/4"&gt;&lt;time&gt;Oct 16, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;As of now, it can be a bit difficult to understand what this tool does. A set of new, clear screenshots and (better) GIFs would be great.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/timrodz/vscode-light-switch/issues/4"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/5"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add more tests
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#5&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/5"&gt;&lt;time&gt;Oct 16, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Currently, the suite of tests is very basic. Ideally, we should be testing the following areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilities i.e. &lt;code&gt;workskpace&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commands i.e. &lt;code&gt;setTheme&lt;/code&gt;, &lt;code&gt;switchThemes&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Command binder - What could possibly go wrong?&lt;/li&gt;
&lt;li&gt;String verification through extension settings and &lt;code&gt;date&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have ideas for any other tests, let me know.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/timrodz/vscode-light-switch/issues/5"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/6"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Audit and improve util/workspace
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#6&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/timrodz"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-OkvlV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/7434353%3Fv%3D4" alt="timrodz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/timrodz"&gt;timrodz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/timrodz/vscode-light-switch/issues/6"&gt;&lt;time&gt;Oct 16, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Currently, &lt;code&gt;workspace&lt;/code&gt; runs methods with little to no checks. We should cover potential breaking cases such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User having multi-root workspaces&lt;/li&gt;
&lt;li&gt;Themes that don't exist (or have been deleted)&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/timrodz/vscode-light-switch/issues/6"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@sloppyperfectionist?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Hans-Peter Gauster&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>vscode</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Anonymous &amp; arrow functions in Javascript</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Wed, 25 Sep 2019 04:26:16 +0000</pubDate>
      <link>https://dev.to/timrodz/anonymous-arrow-functions-in-javascript-36fj</link>
      <guid>https://dev.to/timrodz/anonymous-arrow-functions-in-javascript-36fj</guid>
      <description>&lt;p&gt;I've been exploring with javascript anonymous &amp;amp; arrow functions, and found this quite an interesting puzzle: what are the return types of these functions? Bonus points for an explanation of how some of these work (or not)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;getKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&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="na"&gt;getKeyArrow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;getKeyArrowCall&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// function&lt;/span&gt;
&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getKeyArrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getKeyArrowCall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: I changed getKey to be a bit more difficult. The previous version executed &lt;code&gt;return this.key;&lt;/code&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Utility of Delegates and Events in Unity</title>
      <dc:creator>Juan Alejandro Morais</dc:creator>
      <pubDate>Wed, 25 Sep 2019 00:18:21 +0000</pubDate>
      <link>https://dev.to/timrodz/the-utility-of-delegates-and-events-in-unity-48k1</link>
      <guid>https://dev.to/timrodz/the-utility-of-delegates-and-events-in-unity-48k1</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="http://www.timrodz.com/blog/the-utility-of-delegates-and-events-in-unity/" rel="noopener noreferrer"&gt;timrodz.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="https://twitter.com/damagefilter/" rel="noopener noreferrer"&gt;@damagefilter&lt;/a&gt; wrote a more advanced tutorial regarding events in Unity. Go check it out &lt;a href="http://www.indiedb.com/members/damagefilter/blogs/event-and-unity" rel="noopener noreferrer"&gt;here&lt;/a&gt; 😄.&lt;/p&gt;

&lt;p&gt;¡Hola! My name is Juan Rodriguez. I am a Panamanian data &amp;amp; game developer and programmer based in New Zealand. This blog post was written for &lt;a href="http://www.notgdc.fun/" rel="noopener noreferrer"&gt;notGDC&lt;/a&gt; as I wanted to contribute some of my knowledge with the community. It is aimed towards programmers looking to get the most out of Unity, no matter the skill level. The initial stages will be fairly basic as I want everyone to understand this tutorial, so feel free to skip parts as you wish! (Or just grab the &lt;a href="https://github.com/timrodz/unity-callback_examples" rel="noopener noreferrer"&gt;source code&lt;/a&gt;). The tools I used are Unity &lt;a href="https://unity3d.com/unity/qa/patch-releases/2017.3.1p2" rel="noopener noreferrer"&gt;2017.3.1p2&lt;/a&gt; and &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  📩 What
&lt;/h1&gt;

&lt;p&gt;In games, we often encounter situations where we want to notify objects about events that are happening without having to tie them together. Let’s consider the following situation. You have a UI system with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An input field to write a message.&lt;/li&gt;
&lt;li&gt;  A button to send the message.&lt;/li&gt;
&lt;li&gt;  A field to display the message sent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the user clicks the ‘&lt;em&gt;Send Message&lt;/em&gt;’ button, you want to inform the UI controller that a new message has been sent. After this, you will replace the current message with the new one. Lastly, the input field will be cleared up.&lt;/p&gt;

&lt;p&gt;Here’s a GIF of how the game will look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FMad-Hyrax%2Fblog%2Fgh-pages%2Fassets%2Fimg%2Fposts%2Fnotgdc_intro.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%2Fraw.githubusercontent.com%2FMad-Hyrax%2Fblog%2Fgh-pages%2Fassets%2Fimg%2Fposts%2Fnotgdc_intro.gif" alt="Simple, but works."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  📤 How
&lt;/h1&gt;

&lt;p&gt;In order to achieve the desired functionality, we will approach the solution by implementing &lt;strong&gt;delegates&lt;/strong&gt;. Delegates allow us to treat methods as variables, and they work like a mailing list. Subscribers will receive emails and can opt-out at any time. &lt;strong&gt;Note&lt;/strong&gt;: You can subscribe as many methods as you desire. &lt;strong&gt;Events&lt;/strong&gt; are very similar. The main difference is they add a layer of abstraction and protection on the &lt;strong&gt;delegate&lt;/strong&gt; instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list (&lt;a href="https://stackoverflow.com/questions/29155/what-are-the-differences-between-delegates-and-events" rel="noopener noreferrer"&gt;Source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;On the programming side, we are going to have two scripts: an event controller and a UI controller. The event controller will work as our mailing list, and it will have one event: &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt;. Since we want to replace our current message for the input field’s one, so this method will send out new message update requests.&lt;/p&gt;

&lt;p&gt;The UI controller will have an &lt;strong&gt;UpdateMessage&lt;/strong&gt; method subscribed to the &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt; event, and it will work as a &lt;em&gt;listener&lt;/em&gt;. Also, to introduce you to &lt;strong&gt;UnityEvents&lt;/strong&gt; we will play around with our Button and its capabilities, but we’ll get to that later. In essence: Delegates, Events and UnityEvents are very similar.&lt;/p&gt;

&lt;h1&gt;
  
  
  📨 Implementation
&lt;/h1&gt;

&lt;p&gt;Inside Unity, create a new Scene and add the following objects to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Two Empty GameObjects. Rename them ‘&lt;em&gt;UI Controller&lt;/em&gt;’ and ‘&lt;em&gt;Event Controller&lt;/em&gt;’ respectively.&lt;/li&gt;
&lt;li&gt;  Right click on the hierarchy view:

&lt;ul&gt;
&lt;li&gt;  Choose &lt;strong&gt;UI&lt;/strong&gt; → &lt;strong&gt;Button&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Choose &lt;strong&gt;UI&lt;/strong&gt; → &lt;strong&gt;Input&lt;/strong&gt; &lt;strong&gt;Field&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Choose &lt;strong&gt;UI&lt;/strong&gt; → &lt;strong&gt;Text&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: New UI objects will automatically add a &lt;strong&gt;Canvas&lt;/strong&gt; and an &lt;strong&gt;EventSystem&lt;/strong&gt; if your scene does not already have them inside. Why? because the &lt;strong&gt;Canvas&lt;/strong&gt; displays UI elements and the &lt;strong&gt;EventSystem&lt;/strong&gt; handles interactions from inputs that are not keys — They’re necessary to make any UI system work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your scene should look similar to this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2A_T31weY-0J-2ovBf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2A_T31weY-0J-2ovBf.png" alt="A very simple scene."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Applying our solution
&lt;/h1&gt;

&lt;p&gt;Once you have finished setting up your scene, it’s time to create the following C# scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;UIController.cs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;EventController.cs&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These scripts have the same names as our previously created Empty GameObjects. They will be attached to them as components.&lt;/p&gt;

&lt;h2&gt;
  
  
  UIController.cs
&lt;/h2&gt;

&lt;p&gt;Once you create the class, it should look similar to this snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UIController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Use this for initialization&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update is called once per frame&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&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;Since we’re working with UI, we need to include the &lt;em&gt;UnityEngine.UI&lt;/em&gt; library in order to access functionality of UI elements. Between lines &lt;strong&gt;3&lt;/strong&gt; and &lt;strong&gt;5&lt;/strong&gt;, add the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.UI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this is done, remove the &lt;strong&gt;Update&lt;/strong&gt; method— We won’t be needing it. Now that we’ve got our UI library imported, we will proceed to create references to our UI objects in the scene. Inside the UIController class, add the following declarations before the &lt;strong&gt;Start&lt;/strong&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="n"&gt;ButtonSendMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;InputField&lt;/span&gt; &lt;span class="n"&gt;InputField&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="n"&gt;MessageDisplay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to create two methods: &lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; and &lt;strong&gt;UpdateMessage&lt;/strong&gt;. Inside UIController.cs, add the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;UpdateMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_message&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;If you’ve followed the steps correctly, your class should now look like this: &lt;a href="https://gist.github.com/timrodz/db92598bed64de07ff71a1e772df79a2" rel="noopener noreferrer"&gt;Gist url&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Head over to the Unity inspector. Click on the &lt;strong&gt;UI Controller&lt;/strong&gt; GameObject and click on the ‘Add component’, from here you will add the &lt;em&gt;UIController&lt;/em&gt; script. Alternatively, you can also drag and drop the script into the GameObject. Once added, the UI Controller component will have three visible variables. After this, proceed to drag and drop the matching components inside the &lt;strong&gt;Canvas&lt;/strong&gt; object.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The UI Controller &lt;strong&gt;GameObject&lt;/strong&gt; holds &lt;strong&gt;components&lt;/strong&gt; such as the Transform. The UIController script can be attached as a &lt;strong&gt;component&lt;/strong&gt; to any &lt;strong&gt;GameObject&lt;/strong&gt;. In this case, we’re attaching it to the UI Controller GameObject.&lt;/p&gt;
&lt;/blockquote&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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2ANvRgBceLTzj7ZQ39gkHFCA.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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2ANvRgBceLTzj7ZQ39gkHFCA.gif" alt="Adding our components to the UI Controller."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before going forward, we need to talk about &lt;strong&gt;UnityEvents&lt;/strong&gt; and how we’re using them in this tutorial. If you click on the Button inside the canvas, you will see the following component:&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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AKp3DWqTH84BeIZrMrBx9eA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AKp3DWqTH84BeIZrMrBx9eA.png" alt="A button’s view in the Unity inspector."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the bottom of the component’s view, you see a &lt;strong&gt;On Click ()&lt;/strong&gt; field with an empty list and a &lt;strong&gt;+&lt;/strong&gt;/&lt;strong&gt;-&lt;/strong&gt; sign. This is a &lt;strong&gt;UnityEvent&lt;/strong&gt;: They allow you to add methods of objects in the current scene to to it! So, whatever methods you add here will be called when the button receives a click (&lt;strong&gt;onClick&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;If the method you assign is not in the same hierarchy as the component (In this case, our button), its reference might get lost. This can create many undesired scenarios where you have to reassign methods over and over again. To combat this problem, we will add a listener to our Button’s &lt;strong&gt;onClick&lt;/strong&gt; event via code. Inside the &lt;strong&gt;Start&lt;/strong&gt; method, add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ButtonSendMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SendMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;AddListener&lt;/strong&gt; method allows us to subscribe any of our classes’ functions to the desired event; in this case, it’s &lt;strong&gt;onClick&lt;/strong&gt;. The parameter taken is of type &lt;em&gt;UnityAction&lt;/em&gt;, which is essentially anything that is considered a method according to Unity. Now, everytime you click the ‘&lt;em&gt;Send Message&lt;/em&gt;’ button, the &lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; method will be called, no matter the contents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The &lt;strong&gt;AddListener&lt;/strong&gt; method only accepts UnityEvents with no parameters, unless you add them via a Lambda expression.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  EventController.cs
&lt;/h2&gt;

&lt;p&gt;Before going any further, we need to declare our delegate and implement its functionality.&lt;br&gt;
Add the following declarations inside EventController.cs (and before the &lt;strong&gt;Start&lt;/strong&gt; method):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnMessageUpdateRequestDelegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we declare our delegate &lt;strong&gt;OnMessageUpdateRequestDelegate&lt;/strong&gt;. In this part of the declaration, you specify the parameters it will have (no parameters is also valid). In our case, we are adding a string &lt;em&gt;message.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;OnMessageUpdateRequestDelegate&lt;/span&gt; &lt;span class="n"&gt;OnMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re declaring &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt; as an &lt;em&gt;OnMessageUpdateRequestDelegate&lt;/em&gt;. This is because delegates are methods treated as variables. Also, it’s static because we want to be able to access it from other classes without having to save a reference of the EventController (This is entirely optional, and it will vary heavily from your implementation/coding practices).&lt;/p&gt;

&lt;p&gt;Now, replace the &lt;strong&gt;Start&lt;/strong&gt; method for the following one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Event_OnMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-- EventController // Received a request to update message: {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;OnMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Final EventController.cs&lt;/strong&gt;&lt;br&gt;
If you followed the steps correctly, your EventController class should look like this: &lt;a href="https://gist.github.com/timrodz/21e7339f8dab8d3a0ac532b8012f274f" rel="noopener noreferrer"&gt;Gist url&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Back to UIController.cs
&lt;/h2&gt;

&lt;p&gt;Now that our EventController code is ready, it’s time to continue working with our implementation. We now want to subscribe our &lt;strong&gt;UpdateMessage&lt;/strong&gt; method to EventController’s &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt; delegate. Inside the Start method, add this line of code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;EventController.OnMessageUpdateRequest += UpdateMessage;&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We did not use AddListener because delegates/events can simply add/remove listeners with the &lt;strong&gt;+=&lt;/strong&gt;/&lt;strong&gt;-=&lt;/strong&gt; operators. Also, a delegate can equal (=) one method whereas events cannot, they require use of &lt;strong&gt;+=&lt;/strong&gt;/&lt;strong&gt;-=&lt;/strong&gt; assignment operators.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside our SendMessageUpdateRequest method, we will store our message in a temporary string. We do this because we will call EventController’s &lt;strong&gt;Event_OnMessageUpdateRequest&lt;/strong&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Store the input field's text into a string&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;InputField&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;EventController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Event_OnMessageUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&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;If you recall EventController.cs, the contents of &lt;strong&gt;Event_OnMessageUpdateRequest&lt;/strong&gt; method calls the OnMessageUpdateRequest delegate. Because &lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; invokes the event, and &lt;strong&gt;UpdateMessage&lt;/strong&gt; is subscribed to the event, it will also be called.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗳 Method call order
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Button '&lt;em&gt;Send Message&lt;/em&gt;’ &lt;strong&gt;onClick&lt;/strong&gt; &lt;em&gt;UnityEvent&lt;/em&gt; calls &lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; (&lt;em&gt;subscriber&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; &lt;em&gt;method&lt;/em&gt; calls &lt;strong&gt;Event_OnMessageUpdateRequest&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event_OnMessageUpdateRequest&lt;/strong&gt; &lt;em&gt;method&lt;/em&gt; calls &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt; &lt;em&gt;delegate&lt;/em&gt; calls &lt;strong&gt;UpdateMessage&lt;/strong&gt; (&lt;em&gt;subscriber&lt;/em&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This may be confusing, so let me rephrase them in a more readable way: Because &lt;em&gt;method&lt;/em&gt; &lt;strong&gt;SendMessageUpdateRequest&lt;/strong&gt; is subscribed to Button’s &lt;strong&gt;onClick&lt;/strong&gt; &lt;em&gt;UnityEvent&lt;/em&gt;, it will be called every time onClick is also called. Same goes for number 4: Because &lt;em&gt;method&lt;/em&gt; &lt;strong&gt;UpdateMessage&lt;/strong&gt; is subscribed to delegate &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt;, it will be called every time &lt;strong&gt;OnMessageUpdateRequest&lt;/strong&gt; is also called. Hope that eases things up!&lt;/p&gt;

&lt;p&gt;Finally, we do follow the last steps: replace the message, and clear up the input field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;UpdateMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Print the message&lt;/span&gt;
    &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-- UIController // Updating message: {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Replace our message display text with the contents of the message variable&lt;/span&gt;
    &lt;span class="n"&gt;MessageDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Reset the text of our input field&lt;/span&gt;
    &lt;span class="n"&gt;InputField&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Final UIController.cs&lt;/strong&gt;&lt;br&gt;
If you followed all steps correctly, this is how your UIController class should look like: &lt;a href="https://gist.github.com/timrodz/10534c89b7832a50d57dad7a54222a83" rel="noopener noreferrer"&gt;Gist url&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, press play and &lt;strong&gt;cross your fingers.&lt;/strong&gt; If all goes well, congratulations! If not, let me know what’s the issue and we’ll figure it out!&lt;/p&gt;

&lt;h1&gt;
  
  
  💌 Summary
&lt;/h1&gt;




&lt;p&gt;We have learned about delegates, events and UnityEvents in Unity. They are useful variables that can help overcome many programming challenges. I hope you have enjoyed reading this &lt;a href="https://twitter.com/notgdc" rel="noopener noreferrer"&gt;notGDC&lt;/a&gt; blog post.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>csharp</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
