<?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>Forem: Jaime Rios</title>
    <description>The latest articles on Forem by Jaime Rios (@jrioscloud).</description>
    <link>https://forem.com/jrioscloud</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%2F71432%2Fd45dd310-9568-4670-9ba7-674db0b0b5bb.jpg</url>
      <title>Forem: Jaime Rios</title>
      <link>https://forem.com/jrioscloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jrioscloud"/>
    <language>en</language>
    <item>
      <title>How to enable Tailwind Intellisense on TSX Files</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Tue, 26 Jan 2021 18:44:51 +0000</pubDate>
      <link>https://forem.com/jrioscloud/how-to-enable-tailwind-intellisense-on-tsx-files-230b</link>
      <guid>https://forem.com/jrioscloud/how-to-enable-tailwind-intellisense-on-tsx-files-230b</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I've started to experiment with Tailwind, so while setting up my environment when I had this issue, so here is how to setup intellisense on TSX files in nutshell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;Before getting setting up Intellisense, you will need to &lt;a href="https://tailwindcss.com/docs/installation" rel="noopener noreferrer"&gt;install Tailwind in your project&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss" rel="noopener noreferrer"&gt;Tailwind CSS IntelliSense&lt;/a&gt; extension for Visual Studio Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;If you don't have it already, setup a &lt;code&gt;tailwind.config.js&lt;/code&gt; file in your root folder by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;p&gt;Go to VS Code settings, and add the following configuration:&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;// settings.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwindCSS.includeLanguages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;plaintext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&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;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;p&gt;Reload VS Code. My favorite way to do it is to press &lt;code&gt;CMD&lt;/code&gt; + &lt;code&gt;P&lt;/code&gt; and select &lt;code&gt;Reload Window&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's all folks.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Array.reduce() for newbies</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Tue, 06 Oct 2020 23:13:42 +0000</pubDate>
      <link>https://forem.com/jrioscloud/array-reduce-for-newbies-438h</link>
      <guid>https://forem.com/jrioscloud/array-reduce-for-newbies-438h</guid>
      <description>&lt;h3&gt;
  
  
  Prerequisites.
&lt;/h3&gt;

&lt;p&gt;In order to get the most out of this post, it is important for you to be familiar with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using functions with parameters.&lt;/li&gt;
&lt;li&gt;Callback functions.&lt;/li&gt;
&lt;li&gt;How &lt;code&gt;return&lt;/code&gt; works.&lt;/li&gt;
&lt;li&gt;JavaScript Data types.&lt;/li&gt;
&lt;li&gt;Other Array methods like &lt;code&gt;Array.filter&lt;/code&gt; or &lt;code&gt;Array.sort&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In this article will start by getting familiar with some key terms that will make the &lt;code&gt;Array.reduce&lt;/code&gt; easier to understand, those key terms are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducer.&lt;/li&gt;
&lt;li&gt;Accumulator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with a first principles approach and go to the dictionary. According to Dictionary.com, to reduce means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;To bring down to a smaller extent, size, amount, number, etc.&lt;/li&gt;
&lt;li&gt;To lower in degree, intensity, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Synonyms for reduce&lt;/strong&gt;&lt;br&gt;
diminish, decrease, shorten, abridge, curtail, contract, retrench.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this in mind, it now easier to understand what a reducer function is. Simply put, a &lt;strong&gt;reducer function reduces &lt;em&gt;n&lt;/em&gt; input items to a single return value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One of the features that makes &lt;code&gt;Array.reduce&lt;/code&gt; so powerful, is that we can use an accumulator. let us learn what an accumulator is. Going back to the dictionary, an accumulator is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a register used to contain the results of an arithmetical or logical operation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the context of our programs, this register can be a variable that is referring a boolean, an array or an object.&lt;/p&gt;

&lt;p&gt;Now that we know what a reducer function is, let us explore how &lt;code&gt;Array.reduce&lt;/code&gt; works.&lt;/p&gt;




&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Array.reduce&lt;/code&gt; is a method that executes a &lt;em&gt;reducer function&lt;/em&gt; on each element of the array, resulting in single output value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Array.reduce&lt;/code&gt; takes in two parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A reducer function.&lt;/li&gt;
&lt;li&gt;An initial value for the accumulator.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive deeper into the reducer function parameter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducer function
&lt;/h3&gt;

&lt;p&gt;As we have learned before:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;strong&gt;reducer function reduces &lt;em&gt;n&lt;/em&gt; input items to a single return value&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The reducer function we provide to &lt;code&gt;Array.reduce&lt;/code&gt; is executed on each element of the array. This function takes in four parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;accumulator. This is the total value of the accumulator.&lt;/li&gt;
&lt;li&gt;currentItem. Current item of the array.&lt;/li&gt;
&lt;li&gt;currentIndex. Current index of the array.&lt;/li&gt;
&lt;li&gt;sourceArray. This is the array that we want to reduce.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we have the basic concepts. Let's walk trought a few examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of &lt;code&gt;Array.reduce&lt;/code&gt; in JavaScript
&lt;/h2&gt;




&lt;h3&gt;
  
  
  Get the highest number in an array using &lt;code&gt;Array.reduce&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In this example, we will: Use &lt;code&gt;Array.reduce&lt;/code&gt; and define our own &lt;strong&gt;reducer&lt;/strong&gt; function with an &lt;strong&gt;accumulator&lt;/strong&gt; in order to get the highest number in an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="cm"&gt;/**
 * Let's break it down step by step:

 * 1. Define an array of numbers.
 * 2. We declare the reducer function that will be applied to each element of the array.
 * 3. Within the reducer function, if the currentItem is greater than the accumulator, we will return the currentItem.
 * 4. We invoke numbers.reduce() passing our reducer function as a first parameter and 0 as an initial value for our accumulator. * 5. We store the value returned by numbers.reduce() in a variable called average.
 */&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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="c1"&gt;// 1. &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducerFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sourceArray&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;// 2. &lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;currentItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3.&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;accumulator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 🤓 Notice that the value that we return in the reducer function, will be the value of the accumulator the next time the reducer function is invoked.&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;highestNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&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="nx"&gt;reducerFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 4 and 5. Notice that 0 is the initial value for our accumulator.&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Highest number is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;highestNumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finding an Average with the Array.reduce
&lt;/h3&gt;

&lt;p&gt;Imagine you have an array of products coming from the back end. In this example we will get the average price of a product in an array.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="cm"&gt;/**
 * One more time, let's break it down step by step:

 * 1. Define an array of products.
 * 2. We declare the reducer function that will be applied to each element of the array.
 * 3. Within the reducer function, we summ the price of each product to the total.
 * 4. When we reached the last item in the array, we devide it by the number of elements in the array..
 * 5. We invoke products.reduce() passing our reducer function as a first parameter and 0 as an initial value for our accumulator which now is called total. 
 * 6. We store the value returned by products.reduce() in a variable called average.

 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;// 1.&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;29.76&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pineapple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;41.85&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;melon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;46.5&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;reducerFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array&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;// 2.&lt;/span&gt;
  &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// 4.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&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;average&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&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="nx"&gt;reducerFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//5 and 6.&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;average&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 39.37&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
   Other resources:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce" rel="noopener noreferrer"&gt;Array.protype.reduce on MDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3schools.com/jsref/jsref_reduce.asp" rel="noopener noreferrer"&gt;Array.reduce on W3C&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all folks. Thanks for taking the time for learning this article. &lt;/p&gt;




&lt;p&gt;I teach working professionals to code so they can get their first job in tech. If you further questions, you can ask here or &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;DM me on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>codenewbie</category>
      <category>beginners</category>
    </item>
    <item>
      <title>As a BackEnd Dev, what is your biggest struggle while learning Front End Technologies?</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Mon, 23 Mar 2020 04:41:38 +0000</pubDate>
      <link>https://forem.com/jrioscloud/as-a-backend-dev-what-is-your-biggest-struggle-while-learning-front-end-technologies-1b46</link>
      <guid>https://forem.com/jrioscloud/as-a-backend-dev-what-is-your-biggest-struggle-while-learning-front-end-technologies-1b46</guid>
      <description>&lt;p&gt;For me, the biggest struggle while learning Front End Technologies was to distiguish between what is worth learning and revelant and what is not. &lt;/p&gt;

&lt;p&gt;It was early 2016, when Angular 2 was a romour, IE was still supported, flexbox was emerging but not yet supported by most modern browsers. &lt;/p&gt;

&lt;p&gt;A few questions that exemplify my struggle were the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desciding between using &lt;a href="https://bower.io/" rel="noopener noreferrer"&gt;bower&lt;/a&gt; and &lt;a href="//npmj.s"&gt;npm&lt;/a&gt; as a package manager.&lt;/li&gt;
&lt;li&gt;Choosing a first JS freamework to learn, my candidates were: Angular, Angular 2 that was about to be realeased, Ember or React.&lt;/li&gt;
&lt;li&gt;Should I learn ES6?&lt;/li&gt;
&lt;li&gt;Should I learn Typescript or CoffeeScript?&lt;/li&gt;
&lt;li&gt;Grunt or Gulp? What about Yeoman?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about you:&lt;/p&gt;

&lt;p&gt;As a BackEnd Dev, what is your biggest struggle while learning Front End Technologies?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>discuss</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Solving my own problem with Software</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Mon, 27 May 2019 05:59:33 +0000</pubDate>
      <link>https://forem.com/jrioscloud/solving-my-own-problem-with-software-3378</link>
      <guid>https://forem.com/jrioscloud/solving-my-own-problem-with-software-3378</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt; : I made a mobile-only, PWA. &lt;br&gt;
Link to the app ➡ &lt;a href="https://simpleunitconverter.netlify.com/" rel="noopener noreferrer"&gt;https://simpleunitconverter.netlify.com/&lt;/a&gt;&lt;br&gt;
Link to the repo ➡ &lt;a href="https://github.com/papaponmx/simple-unit-converter" rel="noopener noreferrer"&gt;https://github.com/papaponmx/simple-unit-converter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey guys, this is a short post, just to let you know that I just launched a PWA that solves a very personal problem. &lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When I go to the gym, three situations coincide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I use an app that allows you to use pounds or kilograms but not both.&lt;/li&gt;
&lt;li&gt;My gym uses pounds for machines and kilograms for dumbbells.&lt;/li&gt;
&lt;li&gt;Therefor I need a way to constantly convert units from pounds to kilograms. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let us explore the alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I could do it mentally, but I will not too lazy for that.&lt;/li&gt;
&lt;li&gt;There is an app, but I don't want to see commercials, neither use 25 MB for such a simple app space on my device, nor want to see commercials.&lt;/li&gt;
&lt;li&gt;Just Google it, I could but that means turning on the mobile data. That seems trivial, but I start to get notifications from social apps. The problem is that they induce me train for more time than I should, and make me more prone to injuries due to bad form.&lt;/li&gt;
&lt;li&gt;There is a website for that. Kind of, but they are not fully responsive not PWAs.&lt;/li&gt;
&lt;li&gt;Create a PWA connected to the cloud in order to track your own trainings. I didn't think of that at the time thinking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The solution 🤓
&lt;/h2&gt;

&lt;p&gt;Use my knowledge and make a PWA with these features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;️Bidirectional KG to LBS Unit Conversion 🏋️‍&lt;/li&gt;
&lt;li&gt;Dark Theme as default 🌑&lt;/li&gt;
&lt;li&gt;Screen reader tested 🔉&lt;/li&gt;
&lt;li&gt;No User tracking 🔍&lt;/li&gt;
&lt;li&gt;No Ads 📈&lt;/li&gt;
&lt;li&gt;No 💩&lt;/li&gt;
&lt;li&gt;Open source 📚&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The tech stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hosted on &lt;a href="https://netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt; as a boilerplate.&lt;/li&gt;
&lt;li&gt;State management with React Hooks and Context API.&lt;/li&gt;
&lt;li&gt;Styled Components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Link to the app ➡ &lt;a href="https://simpleunitconverter.netlify.com/" rel="noopener noreferrer"&gt;https://simpleunitconverter.netlify.com/&lt;/a&gt;&lt;br&gt;
Link to the repo ➡ &lt;a href="https://github.com/papaponmx/simple-unit-converter" rel="noopener noreferrer"&gt;https://github.com/papaponmx/simple-unit-converter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers guys.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Progressive Enhancement: Respecting web browser preferences in a post ES6 world</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Wed, 22 May 2019 13:04:53 +0000</pubDate>
      <link>https://forem.com/jrioscloud/progressive-enhancement-respecting-web-browser-preferences-in-a-post-es6-world-p4o</link>
      <guid>https://forem.com/jrioscloud/progressive-enhancement-respecting-web-browser-preferences-in-a-post-es6-world-p4o</guid>
      <description>&lt;p&gt;Cover Image By: &lt;a href="https://www.flickr.com/photos/ixtussy/" rel="noopener noreferrer"&gt;Tom Davidson&lt;/a&gt; on &lt;a href="https://www.flickr.com/photos/ixtussy/11713369553/in/photolist-cK6GNN-7XxycZ-bkzTMb-ikG4Zi-4poorm-iR55Ft-5Vd1yv-2wP8hr-269mXaZ-gPq5z-56CF87-834MXP-f5CHSg-dbebug-nDc7V-f5ST7C-83sBpV-f5CMJ8-rrsHEA-f5SZBA-8u65wU-2q3H5t-pw6Ct1-aayTpv-27e2GBR-63wjvq-ppW4DG-4kSh9q-2cG9tvq-8bTRKc-f5SXZU-8u65Cd-nDcoZ-4ihie1-f5SWkm-jw1zQ-f5CBit-9w6fWF-f5T4wo-23nq5PX-4VrVzC-f5CAv6-bGHjLF-sthVp-279U2yQ-4Ra9zX-kWu4hK-qqw2bt-2977WV" rel="noopener noreferrer"&gt;Flickr&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;After Google IO, and watching &lt;a href="https://www.youtube.com/watch?v=2KhRmFHLuhE" rel="noopener noreferrer"&gt;a&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=K2JzIUIHIhc" rel="noopener noreferrer"&gt;few talks&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=c0oy0vQKEZE" rel="noopener noreferrer"&gt;about elevating&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=-xZHWK-vHbQ" rel="noopener noreferrer"&gt;web capabilities&lt;/a&gt;, I got inspired. So here is &lt;a href="https://en.wikipedia.org/wiki/The_Bridge_Builder" rel="noopener noreferrer"&gt;a bridge for you guys&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Progressive Enhancement?
&lt;/h2&gt;

&lt;p&gt;In a nutshell, &lt;em&gt;Progressive Enhancement&lt;/em&gt; is a philosophy for developing web applications and this are the principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic content should be accessible to all web browsers.&lt;/li&gt;
&lt;li&gt;Basic functionality should be accessible to all web browsers.&lt;/li&gt;
&lt;li&gt;Sparse, semantic markup contains all content.&lt;/li&gt;
&lt;li&gt;Enhanced layout is provided by externally linked CSS.&lt;/li&gt;
&lt;li&gt;Enhanced behavior is provided by unobtrusive, externally linked JavaScript.&lt;/li&gt;
&lt;li&gt;End-user web browser preferences are respected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An alternative to &lt;em&gt;PE&lt;/em&gt; is &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Fault_tolerance" rel="noopener noreferrer"&gt;Graceful Degradation&lt;/a&gt;&lt;/em&gt;(GD). The difference is that PE goes from simple to complex while GD goes the other way around.&lt;/p&gt;

&lt;p&gt;I've written &lt;a href="https://dev.to/papaponmx/in-praise-of-accessibility-outline-3m78"&gt;before&lt;/a&gt; &lt;a href="https://dev.to/papaponmx/accessible-fonts-for-people-in-a-hurry-387"&gt;about accessibility&lt;/a&gt; and will write another post for common heuristics for web development. &lt;/p&gt;

&lt;p&gt;More than persuading you to support IE or holding back on &lt;a href="https://caniuse.com/#search=grid" rel="noopener noreferrer"&gt;CSS Grid&lt;/a&gt;, my goal is to make you aware of new APIs we can use in order to comply with the last point on the list: &lt;em&gt;End-user web broser preferences are respected&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Respecting web browser preferences
&lt;/h2&gt;

&lt;p&gt;Even if you are not aware of it, the browser exposes information about the user preferences, so let us walk through a few of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Font system default
&lt;/h3&gt;

&lt;p&gt;Another reason for using the system's default font is web performance, since there are no additional files to fetch from a server. There are three ways to accomplish this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using the &lt;code&gt;system-ui&lt;/code&gt; value:&lt;br&gt;
This is a value for font-family that represents the default user interface font. Except &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1545745" rel="noopener noreferrer"&gt;for Firefox&lt;/a&gt;, it is supported by &lt;a href="https://caniuse.com/#search=system-ui" rel="noopener noreferrer"&gt;most recent modern browsers&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply system fonts by calling them using &lt;code&gt;font-family&lt;/code&gt;:&lt;br&gt;
I recommend hiding this behind a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@supports" rel="noopener noreferrer"&gt;feature query&lt;/a&gt;, as a fallback.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-apple-system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Roboto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Apple Color Emoji"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI Emoji"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI Symbol"&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;ol&gt;
&lt;li&gt;Using a polyfill.
Depending on your use case, this might be a last resource alternative. This is available as an npm package and this is the link: &lt;a href="https://www.npmjs.com/package/font-family-system-ui" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/font-family-system-ui&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Do Not track
&lt;/h3&gt;

&lt;p&gt;This might be a controversial one. But the only fact that the user does not want you to,  should  be enough reason to stop monitoring their behavior. This is an opinion, but &lt;a href="https://en.wikipedia.org/wiki/Right_to_privacy" rel="noopener noreferrer"&gt;privacy is a human right&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/navigator/doNotTrack" rel="noopener noreferrer"&gt;Do Not Track API&lt;/a&gt; is &lt;a href="https://caniuse.com/#search=doNotTrack" rel="noopener noreferrer"&gt;supported by modern browsers &lt;strong&gt;except Safari&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is what an implementation might look like:&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="cm"&gt;/**
 * "1" if DNT is enabled
 * "0" if the user opted-in for tracking
 * "unspecified" otherwise
 **/&lt;/span&gt; 

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Initialize Google Analytics scripts&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Ask user if it is ok to track&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// DO NOT TRACK&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack" rel="noopener noreferrer"&gt; Do Not Track on MDN&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default to user preferred language
&lt;/h3&gt;

&lt;p&gt;Depending on your app, there might be an internationalization(i18n) implementation in your app. There is a way to default to user's language if supported, Instead of inferring it from their IP, location or your app preferences. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  User &lt;code&gt;prefers-color-scheme&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;prefers-color-scheme&lt;/code&gt; is a media feature that as the name implies, allows us to detect if the user has requested the system use a light or dark color theme.&lt;/p&gt;

&lt;p&gt;This was &lt;a href="https://hacks.mozilla.org/2019/05/firefox-67-dark-mode-css-webrender/" rel="noopener noreferrer"&gt;shipped on Firefox 67&lt;/a&gt;, it is supported on Safari 12.1 but as the time of this writing, &lt;a href="https://caniuse.com/#search=prefer" rel="noopener noreferrer"&gt;support is still missing in most modern browsers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is the link to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme" rel="noopener noreferrer"&gt;&lt;code&gt;prefers-color-scheme&lt;/code&gt; on MDN&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  User &lt;code&gt;prefers-reduced-motion&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Similar to the previous point, we can detect if the user prefers to have less animations. This might be due to accessibility concerns, or mere preference. I can see why this might be a concern if you have rich CSS animations, 3D Graphics or VR. &lt;/p&gt;

&lt;p&gt;The implementation in CSS is rather simple, here is what the code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.animation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vibrate&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;linear&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt; &lt;span class="nb"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.animation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;Further resources:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion" rel="noopener noreferrer"&gt;&lt;code&gt;prefers-reduced-motion&lt;/code&gt; on MDN&lt;/a&gt;.&lt;br&gt;
Here is a great article if you would like to look further into this: &lt;a href="https://css-tricks.com/introduction-reduced-motion-media-query/" rel="noopener noreferrer"&gt;https://css-tricks.com/introduction-reduced-motion-media-query/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all folks, thanks for your taking the time to read this. You can read my other posts on &lt;a href="https://dev.to/papaponmx"&gt;https://dev.to/papaponmx&lt;/a&gt; or say &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;hi on Twitter&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

</description>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Accessible fonts for people in a hurry</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Sat, 20 Apr 2019 16:45:45 +0000</pubDate>
      <link>https://forem.com/jrioscloud/accessible-fonts-for-people-in-a-hurry-387</link>
      <guid>https://forem.com/jrioscloud/accessible-fonts-for-people-in-a-hurry-387</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: &lt;br&gt;
Fonts can be more a11y friendly by: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a bigger font size.&lt;/li&gt;
&lt;li&gt;Having sans-serif font Families.&lt;/li&gt;
&lt;li&gt;More contrasting colors.&lt;/li&gt;
&lt;li&gt;If you don't have a11y first, could you provide an a11y theme?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alternative ways to interact with the web
&lt;/h2&gt;

&lt;p&gt;My current job and a few post inspired this post. There is a keen interest on the business side towards making the application more accessible and we are doing some heavy lifting in order to facilitate the interaction for most users.&lt;/p&gt;

&lt;p&gt;Some of those include but are not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cognitive impairments (head injury, autism, developmental disabilities) and learning disabilities (such as dyslexia, dyscalculia or ADHD).&lt;/li&gt;
&lt;li&gt;Visual impairment such as low-vision, complete or partial blindness, and color blindness.&lt;/li&gt;
&lt;li&gt;Hearing-related disabilities.&lt;/li&gt;
&lt;li&gt;Motor or dexterity impairment such as carpal tunnel syndrome, artritis and repetitive strain injury.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of us interact with a mouse and a keyboard, but there is a wide range of people that just can't. Depending on their condition, our users might use assistive software or devices like: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screen readers like &lt;a href="https://www.freedomscientific.com/products/software/jaws/" rel="noopener noreferrer"&gt;JAWS&lt;/a&gt;, &lt;a href="https://support.google.com/accessibility/android/answer/6283677?hl=en" rel="noopener noreferrer"&gt;talkback&lt;/a&gt;, &lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.amazon.com/Braille-Overlays-for-Computer-Keyboards/dp/B00I5PPUKM/ref=sr_1_1_sspa?keywords=braille%20keyboard&amp;amp;qid=1555548524&amp;amp;s=gateway&amp;amp;sr=8-1-spons&amp;amp;psc=1" rel="noopener noreferrer"&gt;braile keyboard&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.youtube.com/watch?v=V1yoOLhx_qA&amp;amp;list=PLNYkxOF6rcICWx0C9LVWWVqvHlYJyqw7g&amp;amp;index=2" rel="noopener noreferrer"&gt;switch device&lt;/a&gt; or their phone volume buttons in the same way.&lt;/li&gt;
&lt;li&gt;A keyboard without a mouse.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://chrome.google.com/webstore/detail/opendyslexic-font-for-chr/cdnapgfjopgaggbmfgbiinmmbdcglnam" rel="noopener noreferrer"&gt;Chrome extension&lt;/a&gt; due to dislexya. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we can do about it
&lt;/h2&gt;

&lt;p&gt;As you can see, there is a wide variety on conditions, for the purpose of this post,  visual impairment is the most relevant for us. Keep in mind that it also includes people wearing glasses due to some degree of &lt;a href="https://medical-dictionary.thefreedictionary.com/Miopia" rel="noopener noreferrer"&gt;myopia&lt;/a&gt;, &lt;a href="https://www.webmd.com/eye-health/astigmatism-eyes" rel="noopener noreferrer"&gt;astigmatism&lt;/a&gt;. Even poor illumination or a bad monitor can pose some difficulty for experiencing the web.&lt;/p&gt;

&lt;p&gt;Let us begin with the end in mind. Most developers are not expected to design, but there are situations where our input is required, so I want to give you some &lt;a href="https://www.thefreedictionary.com/heuristic+rule" rel="noopener noreferrer"&gt;heuristics&lt;/a&gt; in order to make some a11y aware decisions. &lt;/p&gt;

&lt;p&gt;In this post, our goal is &lt;strong&gt;to improve the fonts for readability&lt;/strong&gt;.  According to Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Readability&lt;/strong&gt; is the ease with which a reader can understand a written text. In natural language, the readability of text depends on its content and its presentation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;As a rule of thumb, readability most come first&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make fonts bigger
&lt;/h3&gt;

&lt;p&gt;Fonts serve different purposes, they help determine the atmosphere of a website, might even remind us of things and help us better convey a message.&lt;/p&gt;

&lt;p&gt;In a world with &lt;a href="https://www.statista.com/statistics/284202/mobile-phone-internet-user-penetration-worldwide/" rel="noopener noreferrer"&gt;ever more mobile internet access&lt;/a&gt;, having a smaller font might be a good optimization, specially since screens are smaller on mobile devices. However passing a certain threshold, it messes up readability, zooming in might break your layout. Having bigger fonts as a default, makes our layout less prone to break when zooming in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bigger fonts are easier to read from a distance&lt;/strong&gt;. Here is an &lt;a href="https://blog.usejournal.com/your-body-text-is-too-small-5e02d36dc902" rel="noopener noreferrer"&gt;article with use cases&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Could you avoid serifs?
&lt;/h3&gt;

&lt;p&gt;Serifs are the small lines at the end of a larger stroke in a letter. The image below explains it way better.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2F7%2F79%2FSerif-Sans-Comparison.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2F7%2F79%2FSerif-Sans-Comparison.png" alt="Serif illustration" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the early days of the web, there used to be a debate about  why sans serif fonts are better for screens with low resolution. However, the reasons to avoid them are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serif fonts can confuse dyslexics, for example lowercase “p” for a “b”, d”, or “q”.&lt;/li&gt;
&lt;li&gt;Serif fonts can be distracting on narrow spaces. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Colors and contrast
&lt;/h3&gt;

&lt;p&gt;When two colors are similar, if the difference is two subtle, people might not perceive the difference, this is why &lt;strong&gt;contrast matters&lt;/strong&gt;. Here is the contrast definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.merriam-webster.com/dictionary/contrast" rel="noopener noreferrer"&gt;Contrast&lt;/a&gt; is the difference or degree of difference between things having similar or comparable natures.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As crazy as it sounds, two people can be seeing the same color, with one hexadecimal value and still perceive a different color. If the ability to perceive the difference between two colors is too high, this is what we call &lt;a href="https://en.wikipedia.org/wiki/Color_blindness" rel="noopener noreferrer"&gt;color blindness&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The question that arises is: &lt;strong&gt;How do I if the colors I'm using are contrasting enough?&lt;/strong&gt; I am glad you asked. &lt;/p&gt;

&lt;p&gt;The unit we use as a reference to measure the contrast between two colors, is called &lt;strong&gt;contrast ratio&lt;/strong&gt; A contrast ratio of 4.5:1 is the minimum &lt;a href="https://www.w3.org/TR/WCAG/#contrast-minimum" rel="noopener noreferrer"&gt;Web Content Accessibility Guideline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are &lt;strong&gt;tools to help you pick more contrasting colors&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://colorsafe.co/" rel="noopener noreferrer"&gt;http://colorsafe.co/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://clrs.cc/a11y/" rel="noopener noreferrer"&gt;http://clrs.cc/a11y/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A11y themes
&lt;/h3&gt;

&lt;p&gt;In the later months, having a dark theme has become &lt;a href="https://www.digitaltrends.com/computing/macos-siri-shortcuts-screen-time-ios-wwdc/" rel="noopener noreferrer"&gt;something cool&lt;/a&gt;, &lt;a href="https://www.digitaltrends.com/computing/macos-siri-shortcuts-screen-time-ios-wwdc/" rel="noopener noreferrer"&gt;appreciated by the users&lt;/a&gt; and &lt;a href="https://www.xda-developers.com/facebook-messenger-redesign-dark-theme/" rel="noopener noreferrer"&gt;hype-worthy&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  What does it take to provide a dark theme?
&lt;/h4&gt;

&lt;p&gt;From a "&lt;a href="https://en.wikipedia.org/wiki/First_principle" rel="noopener noreferrer"&gt;First principle's approach&lt;/a&gt;", a dark theme requires two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To have the color's across an application to be defined a variables. I know this might not be necessary but, stick with me for a bit.&lt;/li&gt;
&lt;li&gt;An alternative color palette.&lt;/li&gt;
&lt;li&gt;A mechanism that allows the user to switch themes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The question I am trying to pose is, could we provide an &lt;code&gt;a11y&lt;/code&gt; theme too?&lt;/p&gt;

&lt;p&gt;For starters, an &lt;code&gt;a11y&lt;/code&gt; theme could have two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Even more contrasting colors&lt;/strong&gt;, like &lt;a href="https://marketplace.visualstudio.com/items?itemName=74th.monokai-charcoal-high-contrast" rel="noopener noreferrer"&gt;Monokai Charcoal High Contrast theme&lt;/a&gt; for VS Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dyslexic friendly fonts&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further resources
&lt;/h2&gt;

&lt;p&gt;Tool to check &lt;a href="https://contrast-ratio.com/" rel="noopener noreferrer"&gt;Contrast ratio&lt;/a&gt;.&lt;br&gt;
Video about &lt;a href="https://www.youtube.com/watch?v=VLtYFcHx7ec" rel="noopener noreferrer"&gt;Typefaces for dyslexics&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=wF8f8w6HPoo" rel="noopener noreferrer"&gt;Pulp Fiction Dialog with Typography&lt;/a&gt;.&lt;br&gt;
CSS Tricks on &lt;a href="https://css-tricks.com/updating-a-css-variable-with-javascript/" rel="noopener noreferrer"&gt;Updating a variable with JavasScript&lt;/a&gt;.&lt;br&gt;
Article by Microsoft about  &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts/" rel="noopener noreferrer"&gt;variable fonts&lt;/a&gt;.&lt;br&gt;
Paul Boag's podscast &lt;a href="https://boagworld.com/season/10/episode/1016/" rel="noopener noreferrer"&gt;episode about Web Typography&lt;/a&gt;.&lt;br&gt;
&lt;a href="http://www.hemingwayapp.com/" rel="noopener noreferrer"&gt;Hemingway app&lt;/a&gt;.&lt;br&gt;
Article &lt;a href="https://addyosmani.com/a11y/" rel="noopener noreferrer"&gt;about a11y audits&lt;/a&gt; by &lt;a href="https://twitter.com/addyosmani" rel="noopener noreferrer"&gt;Addy Osmani&lt;/a&gt;&lt;br&gt;
Article: &lt;a href="https://web.archive.org/web/20111101034537/http://www.ilo.gw.utwente.nl/ilo/attachments/032_Masterthesis_Leeuw.pdf" rel="noopener noreferrer"&gt;Special font for dislexya?&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That's all folks, thanks for taking the time to read this article. I'm building a blog with all my blog posts. On the mean time, you peek into my future blog posts along with all the previous ones in this &lt;a href="https://github.com/papaponmx/blog" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can find me as &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;@papaponmx&lt;/a&gt; on your favorite social network.&lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>beginners</category>
      <category>html</category>
    </item>
    <item>
      <title>A hitchhikers guide to web images on 2019</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Sat, 23 Mar 2019 20:47:25 +0000</pubDate>
      <link>https://forem.com/jrioscloud/a-hitchhikers-guide-to-web-images-on-2019-203j</link>
      <guid>https://forem.com/jrioscloud/a-hitchhikers-guide-to-web-images-on-2019-203j</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://www.flickr.com/photos/jfxie/" rel="noopener noreferrer"&gt;JfXie&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The goals of this post is to give you some exposure to the current web capabilities and help you identify some opportunity areas for:&lt;/p&gt;

&lt;p&gt;A few assumptions about you reading this post: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are familiar with HTML.&lt;/li&gt;
&lt;li&gt;You know basic image formats like &lt;code&gt;jpg&lt;/code&gt;, &lt;code&gt;png&lt;/code&gt; and &lt;code&gt;svg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You are somewhat familiar with CSS and enough have enough expertise to read, understand and implement the MDN documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The web is evolving, fast. Nice to have features have become something you as a developer, are expected to be familiar with here are some that are common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internationalization (i18n).&lt;/li&gt;
&lt;li&gt;Front End Routing.&lt;/li&gt;
&lt;li&gt;Responsive web design.&lt;/li&gt;
&lt;li&gt;Front End User Authentication.&lt;/li&gt;
&lt;li&gt;SEO.&lt;/li&gt;
&lt;li&gt;Page Speed Optimization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New features within the HTML spec
&lt;/h2&gt;

&lt;p&gt;The HTML5 spec, is intended to serve a mobile web, you can think of it as two things a set of &lt;a href="https://www.w3schools.com/html/html5_new_elements.asp" rel="noopener noreferrer"&gt;HTML tags&lt;/a&gt;, and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5" rel="noopener noreferrer"&gt;several new APIs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us revise some new tags and attributes one by one, after that I will add an example that uses all of these.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can think of it as an &lt;code&gt;img&lt;/code&gt; tag with more flexibility to display image resources. It allows us to provide higher-density versions of an image to high-&lt;a href="https://en.wikipedia.org/wiki/Dots_per_inch" rel="noopener noreferrer"&gt;DPI&lt;/a&gt; displays. Let us see what it looks like, according to MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The HTML  element contains zero or more  elements and one &lt;a href="" class="article-body-image-wrapper"&gt;&lt;img&gt;&lt;/a&gt; element to provide versions of an image for different display/device scenarios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The HTML &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#attr-srcset" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;&lt;/a&gt; element specifies multiple media resources for the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;, the &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element, or the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;srcset&lt;/code&gt; attribute
&lt;/h4&gt;

&lt;p&gt;This attribute is similar to &lt;code&gt;src&lt;/code&gt;, but used to define multiple images &lt;code&gt;src&lt;/code&gt;, there are many ways to implement this sources&lt;/p&gt;

&lt;p&gt;Declare the &lt;strong&gt;attribute once with multiple images and a src as a default&lt;/strong&gt;. Check original source at &lt;a href="https://webkit.org/demos/srcset/" rel="noopener noreferrer"&gt;webkit.org&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image-src.png"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image-1x.png 1x, 
          image-2x.png 2x,
          image-3x.png 3x, 
          image-4x.png 4x"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other way is to declare multiple sources and within each have one &lt;code&gt;srcset&lt;/code&gt;. You can see it in the example below. The main difference is that the second has a more specfic conditions for image displays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Putting it all together&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/papapon/pen/EMOdWr?editors=1100" rel="noopener noreferrer"&gt;See it on Codepen&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 799px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/200/300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/400/600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/600/800"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A cute black cat showing his love"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;del&gt;New&lt;/del&gt; relevant CSS properties
&lt;/h2&gt;

&lt;p&gt;In case you did not know, spoiler alert, &lt;a href="https://dev.to/olimpioadolfo/does-css4-exist-5ao4"&gt;CSS 4 does not exist&lt;/a&gt;. Instead we have small increments being supported by modern browsers. Here are some properties that is good to be aware of:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;object-position&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As the name suggests, &lt;code&gt;object-position&lt;/code&gt;, defines the way in which an object is defined within a box. It is quite similar to &lt;a href="https://developer.mozilla.org/es/docs/Web/CSS/background-position" rel="noopener noreferrer"&gt;&lt;code&gt;background-position&lt;/code&gt;&lt;/a&gt;. You can &lt;a href="https://codepen.io/robinrendle/pen/raGOOJ" rel="noopener noreferrer"&gt;see the code pen example in&lt;/a&gt;, thanks &lt;a href="https://twitter.com/robinrendle" rel="noopener noreferrer"&gt;@Robin Rendle&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;image-rendering&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This property serves to tell the browser how it should render the image. The values describe the algorithm that will be implemented in order to scale the image, by the time of this writing, the possible values are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;auto&lt;/code&gt;: Default value, the browser's algorithm will determine how to scale the image.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;crisp-edges&lt;/code&gt;: It preserves contrast and edges in the image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pixelated&lt;/code&gt;: As the name suggests, the browser will keep it's pixelated style as the viewport grows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see how this three images behave in &lt;a href="https://codepen.io/robinrendle/pen/XJPPMW" rel="noopener noreferrer"&gt;this example on Codepen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Or check this &lt;a href="https://codepen.io/robinrendle/pen/EaOJeq" rel="noopener noreferrer"&gt;&lt;code&gt;image-rendering&lt;/code&gt; applied to a QR code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image formats
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Apple iPhone 7 Plus, GSM Unlocked, 32GB - Rose Gold (Refurbished)"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://images-na.ssl-images-amazon.com/images/I/51gVm-dTdvL._AC_SY200_.jpg"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"product-image"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200px"&lt;/span&gt; &lt;span class="na"&gt;data-a-hires=&lt;/span&gt;&lt;span class="s"&gt;"https://images-na.ssl-images-amazon.com/images/I/51gVm-dTdvL._AC_SY400_.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lazy loading
&lt;/h2&gt;

&lt;p&gt;Lazy loading images means that they are served slowly and it is avoided until it is necessary. &lt;/p&gt;

&lt;p&gt;When implemented, for the final user it usually means a smaller bundle served, faster loads and a better experience overall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intersection Observer API
&lt;/h3&gt;

&lt;p&gt;For starters, you might want to use the Intersection Observer API. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Simply put, the API provides users a way to observe given elements and monitor changes in their intersection with a given ancestor element, or the viewport itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you use Gatsby, &lt;a href="https://www.gatsbyjs.org/docs/gatsby-link/" rel="noopener noreferrer"&gt;Gatsby Link&lt;/a&gt; is already using it under the hood.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/es/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;Intersection Observer API on MDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://caniuse.com/#search=intersection" rel="noopener noreferrer"&gt;Intersection Observer API support on caniuse.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Great article: &lt;a href="https://www.hweaver.com/intersection-observer-single-page-navigation/" rel="noopener noreferrer"&gt;Master the Intersection Observer API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For modern frameworks here are some npm packages you might want to look into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jamiebuilds/react-loadable" rel="noopener noreferrer"&gt;React Loadable&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hilongjw/vue-lazyload" rel="noopener noreferrer"&gt;Vue Lazy Load&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aljullu/react-lazy-load-image-component#readme" rel="noopener noreferrer"&gt;React Lazy Load Image Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.io/guide/lazy-loading-ngmodules" rel="noopener noreferrer"&gt;Angular Lazy Loading Modules&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Skeletons
&lt;/h2&gt;

&lt;p&gt;Even when you have lazy loading in place, user's internet speed might be slow or interrupted, even in urban areas, even if the user is not aware of it, so it is good to have something in place to the user to see. That's where skeletons come in place.&lt;/p&gt;

&lt;p&gt;A skeleton is &lt;em&gt;a placeholder in a place which need waiting for loading&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You might have seen it before, this is what a skeleton looks like: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Figx7hnjxzobwglbnqj8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Figx7hnjxzobwglbnqj8c.png" title="CSS skeleton example" alt="alt text" width="312" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/oslego/pen/XdvWmd" rel="noopener noreferrer"&gt;https://codepen.io/oslego/pen/XdvWmd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some npm packages you might use in order to implement this feature, but as a rule of thumb, let's use something simpler. &lt;/p&gt;

&lt;h3&gt;
  
  
  Introduce &lt;code&gt;:empty&lt;/code&gt; pseudo-class
&lt;/h3&gt;

&lt;p&gt;According to  MDN Docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;empty&lt;/code&gt; represents any element that has no children. Children can be either element nodes or text (including whitespace). Comments, processing instructions, and CSS content do not affect whether an element is considered empty.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So an skeleton can be as simple as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/*
 * ...your styles
 */&lt;/span&gt;

&lt;span class="nc"&gt;.user-data&lt;/span&gt;&lt;span class="nd"&gt;:empty&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check an animated &lt;a href="https://codepen.io/oslego/pen/XdvWmd" rel="noopener noreferrer"&gt;Skeleton Screen with CSS&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:empty" rel="noopener noreferrer"&gt;&lt;code&gt;:empty&lt;/code&gt; at MDN Docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduce WebP
&lt;/h2&gt;

&lt;p&gt;WebP is an image format designed for the web, it was released on September 2010 and other than Safari, now it is widely &lt;a href="https://caniuse.com/#search=webp" rel="noopener noreferrer"&gt;supported on most modern browsers&lt;/a&gt;. If you check your profile picture on &lt;a href="//dev.to/"&gt;dev.to&lt;/a&gt;, you might find that it is already using it. I'll list a few articles in the last part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://moz.com/learn/seo/mobile-optimization" rel="noopener noreferrer"&gt;MDN Mobile Optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://search.google.com/test/mobile-friendly" rel="noopener noreferrer"&gt;Google's Mobile Testing Tool&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webspeedtest.cloudinary.com/" rel="noopener noreferrer"&gt;Website Speed Test Image Analysis Tool&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.wpkube.com/html5-cheat-sheet/" rel="noopener noreferrer"&gt;HTML5 Cheat Sheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/dimitrinicolas/learn-how-to-automate-your-image-optimization-process-with-lepto-890?utm_source=additional_box&amp;amp;utm_medium=internal&amp;amp;utm_campaign=regular&amp;amp;booster_org="&gt;Learn How to automate your image optimization process with Lepto&lt;/a&gt; by &lt;a href="https://dev.to/dimitrinicolas"&gt;Dimitry Nicholas&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/leptojs/lepto" rel="noopener noreferrer"&gt;Automated image Editing, Optimization and Analysis via CLI and a web interface&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/packages/gatsby-image/" rel="noopener noreferrer"&gt;Gatsby Image&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Lozard JS: Highly performant, light ~1kb and configurable lazy loader in pure JS with no dependencies for responsive images, iframes and more &lt;a href="https://apoorv.pro/lozad.js/demo/" rel="noopener noreferrer"&gt;https://apoorv.pro/lozad.js/demo/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Article about WebP on &lt;a href="https://developers.google.com/speed/webp/" rel="noopener noreferrer"&gt;Google Developers.&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/WebP" rel="noopener noreferrer"&gt;WebP on Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all folks, thanks to making it to the very end, keep on learning. &lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>beginners</category>
      <category>html</category>
    </item>
    <item>
      <title>If you could only achieve one thing as a programmer during the next year, what would it be?</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Mon, 03 Dec 2018 14:44:31 +0000</pubDate>
      <link>https://forem.com/jrioscloud/if-you-could-only-achieve-one-thing-as-a-programmer-during-the-next-year-what-would-it-be--1m9h</link>
      <guid>https://forem.com/jrioscloud/if-you-could-only-achieve-one-thing-as-a-programmer-during-the-next-year-what-would-it-be--1m9h</guid>
      <description>&lt;p&gt;For me it would be reaching 150 customers. &lt;/p&gt;

&lt;p&gt;It implies launching my SaaS and making it open source, and improving the browsing experience for the people that I seek to serve.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Flipping the coin: Should developers design?</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Wed, 28 Nov 2018 03:42:38 +0000</pubDate>
      <link>https://forem.com/jrioscloud/flipping-the-coin-should-developers-design-26ie</link>
      <guid>https://forem.com/jrioscloud/flipping-the-coin-should-developers-design-26ie</guid>
      <description>&lt;p&gt;We all know and have different and loosely held opinions about designers coding. But what about the opposite?&lt;/p&gt;

&lt;p&gt;Personally I've had uncomfortable interactions trying to navigate and &lt;br&gt;
performing critical tasks in both school and tax paying system. &lt;/p&gt;

&lt;p&gt;At the time there feel like Norman Doors, specially a time when I was asked to create a really strong password in order to protect critical information. After a form was submitted, no feedback was presented to the user. Upon further inspection a realized that a fetch request was made to the server and it has a ~5 second latency. If things go wrong, which they did, no feedback was presented to the user. It was really, really painful.&lt;/p&gt;

&lt;p&gt;When you hire a developer, you don't expect her to design, however some UX or UI design is always appreciated. What's your take?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>design</category>
    </item>
    <item>
      <title>Front End Development Automation. Part 4</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Sun, 25 Nov 2018 17:52:55 +0000</pubDate>
      <link>https://forem.com/jrioscloud/front-end-development-automation-part-4-3gjd</link>
      <guid>https://forem.com/jrioscloud/front-end-development-automation-part-4-3gjd</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In this post &lt;strong&gt;we will create part of a system that is part of a bigger one&lt;/strong&gt;. We will focus only on running performance test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In this post I am assuming that you are quite familiar with Git, &lt;a href="https://dev.to/papaponmx/a-gentle-explanation-of-github-webhooks-----d3e"&gt;Github Webhooks&lt;/a&gt;, &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt; and Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NodeJS&lt;/strong&gt;: Here is &lt;a href="https://github.com/papaponmx/performance-tests" rel="noopener noreferrer"&gt;the repo with all the code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;ABC Corp has a &lt;code&gt;SPA&lt;/code&gt; that is core to the business. It needs to perform great on mobile(we will define what great means later). As time goes by, releases become more frequent and there is a pressing need &lt;strong&gt;to ensure that all new releases comply with the &lt;code&gt;performance budget&lt;/code&gt; assigned to it&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;As developers, we must ensure each release must be in a deployable state. For us, deployable means that all tests are passing and new features work as expected in an production-like environment. On top of that, we need/would like to have a way to get instant feedback about the performance of our next release, therefore the proposed solution:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a system that runs performance tests each time a new release is made.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt;. A zero-dependency module that loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file into &lt;code&gt;process.env&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/GoogleChrome/puppeteer" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt;. Headless Chrome Node API.&amp;lt;!-- * &lt;a href="https://github.com/shelljs/shelljs" rel="noopener noreferrer"&gt;ShellJS&lt;/a&gt;. Unix shell commands on top of the Node.js API --&amp;gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/web/tools/lighthouse/#cli" rel="noopener noreferrer"&gt;Lightouse CLI&lt;/a&gt;. Audit our application and get the relevant data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Developing our Analysis tool
&lt;/h2&gt;

&lt;p&gt;Ideally, our next build should always either improve upon the last release or stay within an acceptable range. If things start to deviate, we want to get the relevant data as fast as posible.&lt;/p&gt;

&lt;p&gt;We will create a function that gathers these metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JS Coverage &amp;amp; CSS Coverage. This metric tells us how much code was used, versus how much was loaded.&lt;/li&gt;
&lt;li&gt;Network Requests. Lists the network requests that were made during page load.&lt;/li&gt;
&lt;li&gt;Speed-index. Speed Index shows how quickly the contents of a page are visibly populated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will runs all tests that Lighthouse has available. This is the order in which things should start to happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get the app URL running in a testing/staging/local environment&lt;/strong&gt;. This should be read from a configuration file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate code coverage&lt;/strong&gt;. For now we'll just get it for the home page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run Lighthouse audit&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter information and send it somewhere it can persist.&lt;/strong&gt; This could be either a JSON saved using file system or a Database. As the app matures we'll define it somewhere else
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * puppeteerPerformance.js
*/&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="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;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&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;chromeLauncher&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;lighthouse/chrome-launcher/chrome-launcher&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;fs&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;fs&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;lighthouse&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;lighthouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APP_URL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&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;launchChromeAndRunLighthouse&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;chromeLauncher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&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;chrome&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;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;lighthouse&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="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&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;results&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kill&lt;/span&gt;&lt;span class="p"&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;results&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="c1"&gt;// 2.&lt;/span&gt;
&lt;span class="nf"&gt;launchChromeAndRunLighthouse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;APP_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 3.&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;results&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./results.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The file was saved!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;results&lt;/code&gt; variable could be sent to a database and be stored for historycal comparison.&lt;/p&gt;

&lt;p&gt;In this case, we'll just save it as a JSON file&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Not Creating our Github Action
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bummer&lt;/strong&gt;: &lt;em&gt;at this time, Github actions are in public, beta, and I am on the wait list. So we will use a Github WebHook instead. If you are in a position to authorize my request, I'll be happy to blog about it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NodeJS&lt;/strong&gt;: Here is &lt;a href="https://github.com/papaponmx/performance-tests" rel="noopener noreferrer"&gt;the repo with all the code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have already written a blog post on &lt;a href="https://dev.to/papaponmx/a-gentle-explanation-of-github-webhooks-----d3e"&gt;how to setup Github Webhooks&lt;/a&gt;. In this case I'll create a Heroku app in and use that url for the URL settup.&lt;/p&gt;

&lt;p&gt;Now we need to create a simple Express Application that runs tests everytime a request is recieved.&lt;/p&gt;

&lt;p&gt;We will install express&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&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;APP_STAGING_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APP_PRODUCTION_URL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&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;body-parser&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;fs&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;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lighthousePerfAudits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./audits/lighthousePerfAudits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/run&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Check secret&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-hub-signature&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="cm"&gt;/**
     * Secret is valid,
     * run tests and write json data
     * on both environments
     */&lt;/span&gt;
    &lt;span class="nf"&gt;lighthousePerfAudits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_PRODUCTION_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&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;results&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/production_results.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The file was saved!&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="nf"&gt;lighthousePerfAudits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APP_STAGING_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&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;results&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/staging_results.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The file was saved!&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="c1"&gt;// send response with 200&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// secret is not valid, return 500&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App linstening on &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With this instance in place, we can run scripts everytime a push is deployed to the repository and get our relevant metrics in order.&lt;/p&gt;

&lt;p&gt;There are some lose ends on the application like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where should this data persist?&lt;/li&gt;
&lt;li&gt;Is there a way to just plug it into Github?&lt;/li&gt;
&lt;li&gt;How can we visualize the historic data of our releases performance?&lt;/li&gt;
&lt;li&gt;What does the fox say?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll address those concerns in further posts. I'm also working on an openSource SaaS that solves this questions. You can hit me up on twitter if you have more questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NodeJS&lt;/strong&gt;: Here is &lt;a href="https://github.com/papaponmx/performance-tests" rel="noopener noreferrer"&gt;the repo with all the code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

&lt;p&gt;Further resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/papaponmx/a-gentle-explanation-of-github-webhooks-----d3e"&gt;Previous post about Gihub Webhooks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/papaponmx/front-end-development-automation-with-puppeteer-part-3-3pl6"&gt;Part 3 of this series&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="noopener noreferrer"&gt;Lighthouse documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>webperf</category>
    </item>
    <item>
      <title>My impressions about mentoring</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Sun, 11 Nov 2018 17:00:18 +0000</pubDate>
      <link>https://forem.com/jrioscloud/my-impressions-about-mentoring---5bp2</link>
      <guid>https://forem.com/jrioscloud/my-impressions-about-mentoring---5bp2</guid>
      <description>&lt;p&gt;Hi everyone. I have been serving as a mentor for Front End Development for about two months and I'd love to share my experience with all of you. I've collaborated in three ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;DEV has a Beta feature that connects mentors with mentees and you can choose the area of expertise you'd like for your mentor. This connected me with someone in another country (I'm Mexican) who is eager to be a Full Stack JS Developer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have three friends that are not satisfied with their career choices and are interesting in coding as an alternative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I started a new job and there is an Junior Dev who I help on a regular basis.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd love to tell you what it is like so far and share my two cents if you are in a similar situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be encouraging
&lt;/h2&gt;

&lt;p&gt;We all struggle, even simple ideas don't always feel that way the first time. I've spent hours trying to understand something without any guidance and ended up seeing a 5 min video after which everything just made sense. I've also had the opportunity to see something similar with the mentees.&lt;/p&gt;

&lt;p&gt;Sometimes when I'm learning I feel frustrated and/or stupid. In those moments, a kind word goes a long way. I really appreciate the opportunity to give it to a student.&lt;/p&gt;

&lt;h2&gt;
  
  
  Respect your time and others
&lt;/h2&gt;

&lt;p&gt;This might be obvious for you. Right now I'm working full-time, doing college part time, part time freelancing, getting to 9% body fat and on top of that mentoring. If you can do something to provide some certainty when you schedule a meeting, it helps make things smoother.&lt;/p&gt;

&lt;p&gt;Thinking that &lt;em&gt;I'm spending two free hours today with my mentee while I could be earning X dollars from my client.&lt;/em&gt; Makes me quite uncomfortable. Something that worked for me is to decide before hand, how many hours am I allowed to spend this week for each role.&lt;/p&gt;

&lt;p&gt;If you read &lt;em&gt;The Seven Habits of Highly Effective People&lt;/em&gt;, I am designing and developing something that might help organizing your weeks as the Third Habit describes.&lt;/p&gt;

&lt;h2&gt;
  
  
  People learn in different ways
&lt;/h2&gt;

&lt;p&gt;What helped me learn, might not help you at all, you might even find it confusing. We all have different brain structures and cognition has some nuances for all.&lt;/p&gt;

&lt;p&gt;I found this while sharing resources with a mentee. Some like to read articles but find the documentation quite confusing. Other prefers to see crash courses videos, while a third one prefers to do pair programming.For me, videos with subtitles at twice the speed work like a charm, I can also just read the docs and start coding.&lt;/p&gt;

&lt;p&gt;Do Whatever works best for you but don't give up on learning. Also be kind when you find someone less experienced with a different preference for learning resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share what you know, there is greatness in you
&lt;/h2&gt;

&lt;p&gt;The fact that you are solving real problems, even spending your free time learning more about your craft is something to be applauded. Specially when we always have things like Facebook, Twitter and Netflix to distract us. &lt;/p&gt;

&lt;p&gt;Beware that most of your experiences if you choose so, make you smarter and better. Even your mistakes have value, if you learn from them, you become better, if you share that with us, we all are.&lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS&lt;/em&gt;: If you are and experienced Node JS Dev with extensive experience on SaaS, Distributed Systems and multi-tenant applications I'd love to have you as a mentor. DMs are open at &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;@papaponmx&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A gentle explanation of Github Webhooks</title>
      <dc:creator>Jaime Rios</dc:creator>
      <pubDate>Wed, 12 Sep 2018 21:47:17 +0000</pubDate>
      <link>https://forem.com/jrioscloud/a-gentle-explanation-of-github-webhooks-----d3e</link>
      <guid>https://forem.com/jrioscloud/a-gentle-explanation-of-github-webhooks-----d3e</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;As you know, I have been working a lot on puppeteer lately. Trying to automate the things that I find important, repetitive and boring, or where the &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle" rel="noopener noreferrer"&gt;Pareto principle&lt;/a&gt; can be implemented. This is an in between post that we'll build on top of for the next part of the project.&lt;/p&gt;

&lt;p&gt;The choice to aim for something greater while selecting a topic for this post was not that easy, however, I feel like on the verge of building a product that: is open source, provides you with a lot of value, excites us all and is profitable. All of those four, in that specific order.&lt;/p&gt;

&lt;p&gt;If you want to, you can tweet me &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;@papaponmx&lt;/a&gt;, DMs are open.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are webhooks and why do they matter
&lt;/h2&gt;

&lt;p&gt;In this context, &lt;em&gt;hooks are events you can subscribe to&lt;/em&gt; in order to trigger some action. It is possible that you have been using them for a while without knowing. Within the context of git and Github, there are many events you might want to know about.&lt;/p&gt;

&lt;p&gt;They matter because they allow us to perform some actions only when they are relevant, here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a pull request is created, run all the tests and let me know if they are OK, or not.&lt;/li&gt;
&lt;li&gt;When a new release tag is created, make a summary of all the new features and add it to the &lt;code&gt;CHANGELOG.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When a new issue is rised, send a message to the team via Slack.&lt;/li&gt;
&lt;li&gt;Any time a release is made, run performance test, look for key differences and let me know the results. This is what we are going to do on the next post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a &lt;a href="https://developer.github.com/webhooks/" rel="noopener noreferrer"&gt;link&lt;/a&gt; with more events you can subscribe to.&lt;/p&gt;

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

&lt;p&gt;When some event happens, Github will send you an &lt;em&gt;HTTP POST&lt;/em&gt; letting you us know that the event happen and &lt;em&gt;a payload&lt;/em&gt; providing us with relevant information about it. For example: If you subscribed to &lt;code&gt;pull_request&lt;/code&gt;, they payload will tell us who initiated it, the target and origin branches, etc.&lt;/p&gt;

&lt;p&gt;As you can tell, the payload depends on the event, in the &lt;code&gt;pull_request&lt;/code&gt; payload, we have this information about the repo:&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="c1"&gt;//...&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;135493233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello-World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;full_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Codertocat/Hello-World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Codertocat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21031067&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MDQ6VXNlcjIxMDMxMDY3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avatar_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://avatars1.githubusercontent.com/u/21031067?v=4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gravatar_id&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="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/Codertocat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;followers_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/followers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;following_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/following{/other_user}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gists_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/gists{/gist_id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;starred_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/starred{/owner}{/repo}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subscriptions_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/subscriptions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;organizations_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/orgs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repos_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/repos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;events_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/events{/privacy}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;received_events_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users/Codertocat/received_events&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;site_admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to check the full JSON for &lt;code&gt;pull_request&lt;/code&gt;, &lt;a href="https://developer.github.com/v3/activity/events/types/#pullrequestevent" rel="noopener noreferrer"&gt;here is the link&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we start
&lt;/h2&gt;

&lt;p&gt;I'm glad you asked. Now that we have a general notion of the basics, we need two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To register our webhook.&lt;/li&gt;
&lt;li&gt;Expose an endpoint to our webhook.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Registering our webhook
&lt;/h3&gt;

&lt;p&gt;On your repository, you need to go to Settings, click the Webhooks tab and you should see a screen like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5c7s1nz05epuram7h0pg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5c7s1nz05epuram7h0pg.png" title="Webhooks dashboard" alt="alt text" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One you click the Add webhook button, you will be asked for the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Payload URL&lt;/strong&gt;: This is the endpoint where we will receive the post, something like &lt;code&gt;http://localhost:4567/payload&lt;/code&gt;. But we'll configure this later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content type&lt;/strong&gt;: Comming from a Front End background, &lt;code&gt;application/json&lt;/code&gt; makes more sense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret&lt;/strong&gt;: This is a string. The purpose it serves, is to provide us with a way to ensure that the POST request is coming from Github.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events&lt;/strong&gt;: The events you want to listen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what a webhook added looks like:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsgtjikdm3e015cglndt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsgtjikdm3e015cglndt9.png" title="Webhooks dashboard" alt="alt text" width="784" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers guys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further resources:
&lt;/h3&gt;

&lt;p&gt;Link to my Puppeteer series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/papaponmx/front-end-development-automation-with-puppeteer-part-1-2k9n"&gt;Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/papaponmx/front-end-automation-with-puppeteer-part-2-2pmb"&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/papaponmx/front-end-development-automation-with-puppeteer-part-3-3pl6"&gt;Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.github.com/webhooks/" rel="noopener noreferrer"&gt;Github webhooks Documentation&lt;/a&gt;&lt;br&gt;
 My twitter profile, &lt;a href="https://twitter.com/papaponmx" rel="noopener noreferrer"&gt;@papaponmx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers guys.&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
