<?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: codegram</title>
    <description>The latest articles on Forem by codegram (@codegram).</description>
    <link>https://forem.com/codegram</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%2Forganization%2Fprofile_image%2F1053%2Fe690ef27-216c-4471-9284-f7ec4a6fc8cd.jpg</url>
      <title>Forem: codegram</title>
      <link>https://forem.com/codegram</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/codegram"/>
    <language>en</language>
    <item>
      <title>Firefox, let's focus, please!</title>
      <dc:creator>Verónica Ojeda</dc:creator>
      <pubDate>Wed, 10 Feb 2021 15:04:37 +0000</pubDate>
      <link>https://forem.com/codegram/firefox-let-s-focus-please-b68</link>
      <guid>https://forem.com/codegram/firefox-let-s-focus-please-b68</guid>
      <description>&lt;p&gt;I've decided to share this tiny &lt;del&gt;miny mee&lt;/del&gt; issue that we had in the last project that I worked on, just in case someone is facing the same problem, so they don't have to &lt;del&gt;waste&lt;/del&gt; spend their time too.&lt;/p&gt;

&lt;p&gt;As you might already know, I care about accessibility a lot, but caring is not enough, you need to learn, and there's a lot to learn in this field. Thankfully I'm in a team where everyone is really involved with this topic as well, so we're all learning together. And what a lesson we've learnt here...&lt;/p&gt;

&lt;h2&gt;
  
  
  But first things first, what's the focus?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Focus determines where keyboard events go in the page at any given moment. (...) Focus refers to which control on the screen (an input item such as a field, checkbox, button, or link) currently receives input from the keyboard, and from the clipboard when you paste content. (Source: &lt;a href="https://developers.google.com/web/fundamentals/accessibility/focus"&gt;Web Fundamentals&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They say an image is worth a thousand words and I couldn't agree more so here is a GIF of Codegram's site being used with the keyboard (TAB key) and each focusable element receiving the focus clearly by the blue rectangle.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jw8Mjrfo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.codegram.com/blog/firefox-lets-focus-please/focus_definition.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jw8Mjrfo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.codegram.com/blog/firefox-lets-focus-please/focus_definition.gif" alt="A gif of the simple html site that only had a bunch of links where the user is using the keyboard to navigate through the page with tab key, and the focus never entering any link. Just the body receives the focus."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The mystery of the lost focus on Firefox
&lt;/h2&gt;

&lt;p&gt;We were performing some accessibility plus cross browser testing to check that the site we were building was accessible by keyboard in Chrome, Firefox and Safari. So after we finished the testing, the results were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Chrome&lt;/li&gt;
&lt;li&gt;✅ Safari&lt;/li&gt;
&lt;li&gt;❌ Firefox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was not possible to navigate using the keyboard on Firefox. Focusable elements like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a"&gt;anchors&lt;/a&gt; weren't accesible by keyboard, they weren't receiving the focus as they should.&lt;/p&gt;

&lt;p&gt;We didn't know what could be causing it... was it Tailwind's fault? Maybe Nuxt? Vue? What about PostCSS pollyfill? Because when something is failing, you need to blame someone so who was guilty here, right? But the problem was that it didn't make any sense at all to be anything of the above.&lt;/p&gt;

&lt;p&gt;Sometimes, being a software developer is not that different from being a CSI detective. I decided to begin from the most basic site I could think of and then add different things™ to find out who/what was causing/responsible for the issue.&lt;/p&gt;

&lt;p&gt;So I tried to navigate using the keyboard with the simplest site ever, just a plain html with a few anchor elements. And it still didn't work! Instead of each link, the whole body was being focused. 🤯&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JN3XN5t6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.codegram.com/blog/firefox-lets-focus-please/tabfocus_ko.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JN3XN5t6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.codegram.com/blog/firefox-lets-focus-please/tabfocus_ko.gif" alt="A gif of the simple html site that only had a bunch of links where the user is using the keyboard to navigate through the page with tab key, and the focus never entering any link. Just the body receives the focus."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The typical thing to say is "It works on my machine.", but in my case it's usually the other way around: "It doesn't work on my machine.". I have that gift, I break things. So I asked some coworkers to try it as well and surprise: it was working just for one but not for the rest. 🤯&lt;/p&gt;

&lt;p&gt;This was the clue that I needed to determine that it definitely was something related to Firefox and not to the code or the technologies we used.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what did you do to make it work in everyone's machine?
&lt;/h2&gt;

&lt;p&gt;Well, I did what I do best, research! 🔎 But this time just focusing on the browser and nothing else, not a single technology.&lt;/p&gt;

&lt;p&gt;And finally... 🥁 I found &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1600262"&gt;The Solution™&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the end, it seems to be &lt;strong&gt;an issue related to Firefox and Mac since Catalina OS&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Firefox used to take the value from the user settings in &lt;code&gt;System Preferences &amp;gt; Keyboard &amp;gt; Shortcuts&lt;/code&gt; so just by checking the &lt;code&gt;"Use keyboard navigation to move between controls"&lt;/code&gt; checkbox you could navigate using the keyboard. But that's not working anymore.&lt;/p&gt;

&lt;p&gt;Thankfully it has a quite easy solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;about:config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search for &lt;code&gt;accessibility.tabfocus&lt;/code&gt; and check that it's set to type &lt;code&gt;Boolean&lt;/code&gt; with value &lt;code&gt;true&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mp7TYxMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c1oc166krijvwn1coep1.png" class="article-body-image-wrapper"&gt;&lt;img class="centered" src="https://res.cloudinary.com/practicaldev/image/fetch/s--mp7TYxMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c1oc166krijvwn1coep1.png" alt="A screenshot of Firefox settings for accessibility.tabfocus with value true."&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove it and select &lt;code&gt;Number&lt;/code&gt; instead&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c8qM1m-3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bnmcilwagz3973j3gk3r.png" class="article-body-image-wrapper"&gt;&lt;img class="centered" src="https://res.cloudinary.com/practicaldev/image/fetch/s--c8qM1m-3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bnmcilwagz3973j3gk3r.png" alt="A screenshot of Firefox settings for accessibility.tabfocus being edited. There are three options for the type: Number, Boolean and String."&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on the add button and then enter the value &lt;code&gt;7&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VxOeyxIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iulnya9p33xczzx69nan.png" class="article-body-image-wrapper"&gt;&lt;img class="centered" src="https://res.cloudinary.com/practicaldev/image/fetch/s--VxOeyxIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iulnya9p33xczzx69nan.png" alt="A screenshot of Firefox settings for accessibility.tabfocus with value 7."&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After changing that option in Firefox, I checked back first my super simple html file and it worked! 🎉&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5LBmh_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jwopjtrruteo1tbhcc56.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5LBmh_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jwopjtrruteo1tbhcc56.gif" alt="A gif of the simple html site that only had a bunch of links where the user is using the keyboard to navigate through the page with tab key, and each link receiving the focus correctly."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I checked on the site we were building and indeed it was working as well. 🥳 We finally had the triple check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Chrome&lt;/li&gt;
&lt;li&gt;✅ Safari&lt;/li&gt;
&lt;li&gt;✅ Firefox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mystery solved. 🕵️‍♀️&lt;/p&gt;

&lt;p&gt;Remember, never lose hope, neither the focus! Specially you, Firefox. 🦊&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@stefanbc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Stefan Cosma&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/focus?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
    <item>
      <title>Practical React &amp; Redux - Part 2</title>
      <dc:creator>David Morcillo</dc:creator>
      <pubDate>Tue, 08 Dec 2020 13:24:08 +0000</pubDate>
      <link>https://forem.com/codegram/practical-react-redux-part-2-2ldl</link>
      <guid>https://forem.com/codegram/practical-react-redux-part-2-2ldl</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.codegram.com/blog/practical-react-and-redux-part-2"&gt;Codegram's blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the second part of the React workshop series created by our team. Let's learn about how to create stateful components using React hooks.&lt;/p&gt;

&lt;p&gt;It's been a while but finally awe have released the second part of our React workshop. Remember that you can download the code from the first part in &lt;a href="https://github.com/codegram/practical-react-and-redux"&gt;here&lt;/a&gt;. If you want to follow along just checkout the &lt;code&gt;part-1&lt;/code&gt; tag and update the code as you read.&lt;/p&gt;

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

&lt;p&gt;In the first part we created our first components using React, but we ended the workshop in a bit of a cliffhanger and encountered a bug 🐛. Today we are going to continue our application and start writing some stateful components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stateful components with React hooks
&lt;/h2&gt;

&lt;p&gt;We have created a bunch of stateless components or usually also called "dumb components". Starting now we are going to learn how to add some state to them. First we need to learn what is a React &lt;code&gt;hook&lt;/code&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  useWhat? First overview of hooks
&lt;/h3&gt;

&lt;p&gt;A hook is just a function, period. We can write our hooks and the convention is that they start with the prefix &lt;code&gt;use&lt;/code&gt;. The hooks can only be executed inside components (or other hooks) so usually the hook just return something that can be used by the component.&lt;/p&gt;

&lt;p&gt;A common use of hooks is to reuse some business logic. First let's create a &lt;code&gt;Cat&lt;/code&gt; 😸 component (you need to create the corresponding folder structure as we did before):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/cats/components/cat/Cat.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`This is your new score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Score: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/10&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increase score&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&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="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, use the &lt;code&gt;Cat&lt;/code&gt; component in our application to add a new cat to the view (😸 are also awesome so give them a good score!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/App.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dogs/components/dog/Dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cats/components/cat/Cat&lt;/span&gt;&lt;span class="dl"&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="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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Boira"&lt;/span&gt; &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Black"&lt;/span&gt; &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cat&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Uhura"&lt;/span&gt; &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing really fancy here! Now we have two components that are mostly identical. Let's fix this!. Let's create a &lt;code&gt;pets&lt;/code&gt; module with a hooks folder, and we are going to create our first hook. We are going to copy the &lt;code&gt;onClick&lt;/code&gt; function from the &lt;code&gt;Dog&lt;/code&gt; component and use it inside our hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pets/hooks/useScore.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;increaseScore&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;score&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`This is your new score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the hook is just a function that receives some value, &lt;code&gt;score&lt;/code&gt; in this case, and returns a new object. I added the &lt;code&gt;increaseScore&lt;/code&gt; function to the object so now we can use it inside our components.&lt;/p&gt;

&lt;p&gt;Let's use it in the &lt;code&gt;Dog&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/dogs/components/dog/Dog.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../pets/hooks/useScore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;increaseScore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Score: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/10&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increaseScore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increase score&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&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="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do the same for the Cat component, and we are done here! We have moved some common logic to a hook so now we can focus on fixing our problem. We need to make our view aware of that change in the score or, in other words, make the component stateful!&lt;/p&gt;

&lt;h3&gt;
  
  
  Stateful components using useState
&lt;/h3&gt;

&lt;p&gt;React already includes some hooks. We are going to use &lt;code&gt;useState&lt;/code&gt; to add some &lt;code&gt;state&lt;/code&gt; to our components. The difference between a prop and the state is that we can change the state to re-render our component when something changes!&lt;/p&gt;

&lt;p&gt;Remember that we can use hooks inside other hooks so let's use the &lt;code&gt;useState&lt;/code&gt; hook inside our custom hook &lt;code&gt;useScore&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pets/hooks/useScore.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseScore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseScore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;increaseScore&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;setScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`This is your new score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hold up! There is a lot to digest in the previous snippet so let's review it step by step. First, we rename the hook argument to &lt;code&gt;baseScore&lt;/code&gt; and passed it to the &lt;code&gt;useState&lt;/code&gt; method, this is the initial value of our state. The &lt;code&gt;useState&lt;/code&gt; function returns an array where the first element is our state and the second element is a function to replace our state. I used the word "replace" intentionally because we need to provide a new object always, otherwise it will not be updated (embrace the &lt;code&gt;immutability&lt;/code&gt;!).&lt;/p&gt;

&lt;p&gt;Then I added the &lt;code&gt;score&lt;/code&gt; to the object that our custom hook is returning, so we have access to it in our component. Finally, I used the &lt;code&gt;setScore&lt;/code&gt; function to set a new state when the &lt;code&gt;increaseScore&lt;/code&gt; function is called. Neat, right?&lt;/p&gt;

&lt;p&gt;Let's see how to use it in our components. I am gonna change the &lt;code&gt;Dog&lt;/code&gt; component, and I am gonna leave the &lt;code&gt;Cat&lt;/code&gt; component for yourselves as an excercise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/dogs/components/dog/Dog.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../pets/hooks/useScore&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;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialScore&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increaseScore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialScore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Score: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/10&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increaseScore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increase score&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&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="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="na"&gt;initialScore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also changed the &lt;code&gt;Dog&lt;/code&gt;'s &lt;code&gt;score&lt;/code&gt; prop to &lt;code&gt;initialScore&lt;/code&gt;so we need to update our application as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/App.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dogs/components/dog/Dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cats/components/cat/Cat&lt;/span&gt;&lt;span class="dl"&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="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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Boira"&lt;/span&gt; &lt;span class="na"&gt;initialScore&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Black"&lt;/span&gt; &lt;span class="na"&gt;initialScore&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cat&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Uhura"&lt;/span&gt; &lt;span class="na"&gt;initialScore&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After making all the changes you can refresh your browser and test your application. The view is also updated when we press the button! 🎉&lt;/p&gt;

&lt;p&gt;React includes a small list of hooks: &lt;a href="https://reactjs.org/docs/hooks-reference.html"&gt;https://reactjs.org/docs/hooks-reference.html&lt;/a&gt; but creating your own is straightforward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article we learned about how to add state to our a React application and written our first React hooks. Our application is basic but for a bigger application is better to rely on a state management library and that's the topic for our next article!.&lt;/p&gt;

&lt;p&gt;You can find the code examples in this &lt;a href="https://github.com/codegram/practical-react-and-redux"&gt;repository&lt;/a&gt;. I also tagged the progress for &lt;a href="https://github.com/codegram/practical-react-and-redux/tree/part-2"&gt;part 2&lt;/a&gt; in case you want to check the repository at this specific moment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@henarlanga?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Henar Langa&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>Migrating from WebStorm to Visual Studio Code</title>
      <dc:creator>Verónica Ojeda</dc:creator>
      <pubDate>Wed, 21 Oct 2020 12:58:00 +0000</pubDate>
      <link>https://forem.com/codegram/migrating-from-webstorm-to-visual-studio-code-4o24</link>
      <guid>https://forem.com/codegram/migrating-from-webstorm-to-visual-studio-code-4o24</guid>
      <description>&lt;p&gt;My story with Visual Studio Code (aka VS Code and vscode) hasn't been the typical love story but more of a toxic relationship. We've broken up and got back together so many times I can't even tell. But after all this time and all the experience behind us, I think we're both more mature now and it's the perfect time for this relationship to finally work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xbuzAuCG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/real_programmers.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xbuzAuCG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/real_programmers.png" alt="(A man sits at a computer, programming. Another man behind him looks over his shoulder.)Man: nano? REAL programmers use Emacs.(A dark haired woman appears behind him.)Woman: Hey. REAL programmers use Vim.(Another man appears behind her.)Man: Well, REAL programmers use ed.(Another man appears behind him.)Man: No, REAL programmers use cat.(A woman with a bun appears behindhim.)Woman: REAL programmers use a magnetized needle and a steady hand.(A man enters, facing them all.)Man: Excuse me, but REAL programmers use butterflies. (Holding out a butterfly in front of the computer.)Man: They open their hands and let the delicate wings flap once.(Diagrams of flowing currents.)Man: The disturbances ripple outward, changing the flow of the Eddy currents in the upper atmosphere. These cause momentary pockets of higher-pressure air to form, ...Man: Which act as lenses that deflect incoming cosmic rays, focusing them to strike the drive platter and flip the desired bit.Emacs User: Nice. 'Course, there's an Emacs command to do that.cat User: Oh yeah! Good ol' C-x M-c M-butterfly...(Butterfly man slaps forehead.)&amp;lt;br&amp;gt;
Butterfly man: Dammit, Emacs." title="Real programmers set the universal constants at the start such that the universe evolves to contain the disk with the data they want."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jokes aside, it's a fact that when we get used to working with a specific tool, in the end we all tend to fall in love with it. And this is perfectly normal, you feel more productive and everything feels really easy to do. You can do the exact same thing with many different tools, but with your favourite one you just do it faster and better, it boosts your productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  So why the change, you might ask, right?
&lt;/h2&gt;

&lt;p&gt;When I began to work as a developer, my IDE was Eclipse until one awesome day I discovered the JetBrains suite and it was love at first sight. Since then, I've been working mostly with IntelliJ for the backend stuff and WebStorm for the frontend. &lt;/p&gt;

&lt;p&gt;I just used VS Code for personal projects mostly to try something new, both the IDE and the project itself. But every time I tried to use VS Code in my job, I ended up frustrated, but it was because I wasn't feeling productive. The truth is that I wasn't using the right setup for me.&lt;/p&gt;

&lt;p&gt;At Codegram most of the team use VS Code, on twitter there are many people that I follow (and that I look up to) that use it too, so the real question is, why not? I had given several tries in the past, why not another one?&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration setup
&lt;/h2&gt;

&lt;p&gt;This is my setup to boost your productivity working with VS Code if you're used to working with WebStorm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;I'm not going to explain how they work, since they have a really good description in their respective marketplace pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens"&gt;Git Lens&lt;/a&gt; and  &lt;a href="https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph"&gt;Git Graph&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;VS Code comes with no UI for git, but these two plugins are really helpful to fill some of the features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=xyz.local-history"&gt;Local History&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can't count how many times this has saved the day. With WebStorm or any JetBrains IDE you just right click on any file and go to &lt;strong&gt;Local History &amp;gt; Show History&lt;/strong&gt; and a new windows pop ups with all the changes you've made, so if you want to back an hour ago, you can! Just a minor reminder with this plugin, &lt;strong&gt;add &lt;code&gt;.history/&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree"&gt;Todo Tree&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With JetBrains there is always a TODO tab that lists all the TODOs in the project. This plugin is even better cause you can list the TODOs, the BUGs, etc. and it's customizable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.terminal"&gt;Terminal&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can open the terminal on VS Code with a shortcut, but in WebStorm there's always a tab for that. For once I got used to a button instead of a shortcut. This plugin does the trick by adding a toggle button to your interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Snippets for Code completion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With WebStorm you could create components with the UI, so you could add a new Vue component, or Angular component, with the base structure empty in the created file. There are several snippets for VS Code depending on the framework you work with. In my case, I work with Vue so I'm using &lt;a href="https://marketplace.visualstudio.com/items?itemName=sdras.vue-vscode-snippets"&gt;Vue VS Code Snippets&lt;/a&gt;. I also have &lt;a href="https://marketplace.visualstudio.com/items?itemName=octref.vetur"&gt;Vetur&lt;/a&gt; for Syntax-highlighting among other features to help coding with Vue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard shortcuts
&lt;/h3&gt;

&lt;p&gt;One of the things that made me go back to WebStorm in the past was the shortuts. There are some keyboard shortcuts that once you get used to them, you just can't change them. Well, you could, but you'd rather not. So what I did to make the migration process less painful was to keep the shortcuts that I use the most.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmbL4jOH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://memegenerator.net/img/instances/58006222.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmbL4jOH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://memegenerator.net/img/instances/58006222.jpg" alt='Meme with text "I heard you liked shortcuts, so I made a shortcut to your shortcut"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make it more readable I'm going to use just &lt;code&gt;CMD&lt;/code&gt; instead of &lt;code&gt;CTRL/CMD&lt;/code&gt; since I work with a Macbook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate line:&lt;/strong&gt; In VS Code the setting is usually copy line up/down with &lt;code&gt;SHIFT+OPTION+UP/DOWN&lt;/code&gt; but I prefer to use &lt;code&gt;CMD+D&lt;/code&gt; to duplicate the current line/selection just like in WebStorm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delete line:&lt;/strong&gt; From &lt;code&gt;SHIFT+CMD+K&lt;/code&gt; to &lt;code&gt;CMD+Del&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toggle line comment:&lt;/strong&gt; From &lt;code&gt;CMD+/&lt;/code&gt; to &lt;code&gt;CMD+7&lt;/code&gt;. To be fair this one is exactly the same, but I had it modified in WebStorm as well. By default &lt;code&gt;CMD+7&lt;/code&gt; is the shortcut to go to your bookmark number 7 in JetBrains (you could bookmark lines), but I didn't use it so I find it more useful this way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigation:&lt;/strong&gt; Although we cannot navigate by clicking on methods/classes, there are a couple of shorcuts to go to the previous/next find match. Actually we had to override one of them when setting the new Delete line command. So in this case it would be 'Add Selection To Next Find Match' shortcut from &lt;code&gt;CMD+D&lt;/code&gt; to &lt;code&gt;CTRL+J&lt;/code&gt; and 'Add Selection To Previous Find Match' to &lt;code&gt;CTRL+K&lt;/code&gt;. Why these shortcuts? Well, I used to work with Jira a lot and these were the commands to move through tickets in a search 🤷‍♀️. With these two combined with &lt;code&gt;CMD+F&lt;/code&gt; to search in the file and &lt;code&gt;CMD+SHIFT+F&lt;/code&gt; to search everywhere it does the trick more or less. It's not the same, it's not as fast, but it's all we have when working with with VS Code.&lt;/p&gt;

&lt;p&gt;I must say that there is an &lt;a href="https://marketplace.visualstudio.com/items?itemName=k--kato.intellij-idea-keybindings"&gt;IntelliJ IDEA keybinding plugin&lt;/a&gt;, but it has a huge bug in my opinion. You cannot open files with a shortcut! In the JetBrains suite you hit &lt;code&gt;Double SHIFT&lt;/code&gt; to open a file, the equivalent in VS Code would be &lt;code&gt;CMD+P&lt;/code&gt;. The problem is that &lt;code&gt;Double SHIFT&lt;/code&gt; is not a possible command in VS Code, so since the plugin overrides the VS Code keymap, you end up without being able to open a file neither with &lt;code&gt;Double SHIFT&lt;/code&gt; nor &lt;code&gt;CMD+P&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My list of Pros and Cons
&lt;/h2&gt;

&lt;p&gt;Although this is not a Foo vs Boo post, I always find these kind of comparing lists really useful (I love lists, I'm not going to hide it). This one is based 100% on my experience and my opinion.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebStorm
&lt;/h3&gt;

&lt;p&gt;✅ A lot of functionallity out of the box.&lt;/p&gt;

&lt;p&gt;✅ Really easy-to-use git UI.&lt;/p&gt;

&lt;p&gt;✅ Code completion (i.e. to import a component you just use it in the HTML and it automatically imports it on the script).&lt;/p&gt;

&lt;p&gt;✅ Navigation. Jump to a method, function or variable definition in just one click.&lt;/p&gt;

&lt;p&gt;⚠️ Collaborative development. &lt;a href="https://intellij-support.jetbrains.com/hc/en-us/community/posts/360001795120-Pair-Programming-simultaneously-the-same-way-that-Live-Share-VS%20Code"&gt;People have been asking for this feature&lt;/a&gt; for a while (16 years to be more precise), there were some third party plugins but none of them worked as they should, and finally they have released their own plugin &lt;a href="https://plugins.jetbrains.com/plugin/14896-code-with-me/"&gt;Code With Me&lt;/a&gt; (although it's still on Early Access Program).&lt;/p&gt;

&lt;p&gt;❌ Wants all the RAM and battery all to itself and I already use Chrome, so there's no more room for another RAM eater.&lt;/p&gt;

&lt;p&gt;❌ Private and paid.&lt;/p&gt;

&lt;p&gt;❌ Although it has a community, every time I had a problem it wasn't easy to find a solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I miss the most about WebStorm
&lt;/h3&gt;

&lt;p&gt;Git UI and Navigation features. 😭&lt;/p&gt;

&lt;p&gt;The first one wasn't doing me any good really, cause I was so used to JetBrains UI for Git that it made me dependant on it. It boosted my productivity, and I find features like Project Update (&lt;code&gt;CTRL/CMD+T&lt;/code&gt;) really helpful. This would do &lt;code&gt;git fetch &amp;amp;&amp;amp; git pull&lt;/code&gt; just with a keyboard shortcut. But in the end you forget what's really going on and that can be dangerous.&lt;/p&gt;

&lt;p&gt;Opening files with &lt;code&gt;Double SHIFT&lt;/code&gt;. It might sound silly, but once you get used to the double shift everything else feels like it's taking too much time. I still hit &lt;code&gt;Double SHIFT&lt;/code&gt; a lot of times before going with the &lt;code&gt;CMD+P&lt;/code&gt; 😂. There is &lt;a href="https://github.com/microsoft/vscode/issues/5280"&gt;an issue&lt;/a&gt; open, hopefully they will pay attention to it some day! (which probably would happen once I'm used to the &lt;code&gt;CMD+P&lt;/code&gt; command)&lt;/p&gt;

&lt;p&gt;But the hardest feature to give up is definetly jumping to a method, function or variable definition in just one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code
&lt;/h3&gt;

&lt;p&gt;✅ Free and Open Source.&lt;/p&gt;

&lt;p&gt;✅ Fully Customizable.&lt;/p&gt;

&lt;p&gt;✅ Great community.&lt;/p&gt;

&lt;p&gt;✅ Really fast, it takes less than one second to open.&lt;/p&gt;

&lt;p&gt;✅ Shares RAM and battery with the rest of my computer.&lt;/p&gt;

&lt;p&gt;✅ Collaborative development with &lt;a href="https://visualstudio.microsoft.com/services/live-share/"&gt;Live Share&lt;/a&gt; to do some pair programming.&lt;/p&gt;

&lt;p&gt;✅ Format just the modified lines.&lt;/p&gt;

&lt;p&gt;❌ Lack of some out of the box functionallity.&lt;/p&gt;

&lt;p&gt;❌ Code completion.&lt;/p&gt;

&lt;p&gt;❌ Navigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I like the most about VS Code
&lt;/h3&gt;

&lt;p&gt;The fact that I can work without burning my fingers cause the CPU is using all the resources available 🔥and also that I can work without being plugged in all the time cause my laptop runs out of battery. 🔋&lt;/p&gt;

&lt;p&gt;I never did pair programming before, and I have done it just a couple of times so far but it's a really nice feature to have. And especially helpful when you work remotely, so now that most people are working remotely due to COVID I think it's essential.&lt;/p&gt;

&lt;p&gt;Even though I had it in the cons list as "lack of features out of the box", since it comes with no Git UI, I'm finding it really good for me, cause now thanks to the plugins I have all the visual support that I need but also I have control over git again through the command line. Just as I said above, I think that it can be dangerous to rely 100% on a GUI for git.&lt;/p&gt;

&lt;p&gt;Finally, there's a tiny miny feature on VS Code that means the world to me. When it comes to formatting code, IntelliJ IDEA has so many configurable options in the &lt;code&gt;.editor&lt;/code&gt; file, with VS Code you can just set a few of them in that file. That's why I used to think JetBrains did it better, cause it allowed you to set more options. There are other formatting options like formatting code based on ESLint or Prettier, the most used one. But in the end is usually a pain in the ass, people work with different IDEs, different formatting options and in my experience the result usually is a mess. When you do a Pull Request there are 100 changes and 99 are because of the formatting. Setting the &lt;strong&gt;"Editor: Format On Save Mode" to "modifications"&lt;/strong&gt; has saved my life. With that set, &lt;strong&gt;it only formats the lines you modify!&lt;/strong&gt; 👏🏻 How cool is that, right?!&lt;/p&gt;

&lt;p&gt;If I'm being honest, this is the main reason why I decided to give VS Code another chance and this feature along with everything explained above is what made me stay.&lt;/p&gt;

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

&lt;p&gt;I'm not saying that switching tools is better than sticking to one or viceversa.&lt;/p&gt;

&lt;p&gt;If you feel comfortable with a tool and don't feel like changing it, it's fine. If you want to give new tools a try, that's fine as well. You might fall in love, either with the new tool or with your previous tool all over again.&lt;/p&gt;

&lt;p&gt;Am I going to stick to VS Code? Who knows 🤔 It will depend on my needs and how they keep evolving.&lt;/p&gt;

&lt;p&gt;What about you? Which IDE or Text Editor is your favourite to code and why? Have you ever tried to migrate to another one? Tell us &lt;a href="https://twitter.com/codegram"&gt;on twitter&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@7bbbailey?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Barth Bailey&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/migration?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>But Lighthouse says I'm accessible! · Part 2</title>
      <dc:creator>Verónica Ojeda</dc:creator>
      <pubDate>Fri, 25 Sep 2020 11:26:22 +0000</pubDate>
      <link>https://forem.com/codegram/but-lighthouse-says-i-m-accessible-part-2-4gid</link>
      <guid>https://forem.com/codegram/but-lighthouse-says-i-m-accessible-part-2-4gid</guid>
      <description>&lt;p&gt;In &lt;a href="https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible-part-one"&gt;the previous post&lt;/a&gt; we saw how to score 100 in accessibility in Lighthouse but still not having an accessible site. It's quite common to leave the a11y check for the end of the project, run some automatic tools, fix almost all the bugs they report and that's it.&lt;/p&gt;

&lt;p&gt;But at this point you should know that's not enough, not even close to enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  So... what can we do to improve accessibility? 🤔
&lt;/h2&gt;

&lt;p&gt;Instead of developing a web and then checking for the accessibility, what if we try to be a little bit more empathetic with everyone and change the way we design and develop to take all of this into account from the very beginning?&lt;/p&gt;

&lt;p&gt;And by everyone I mean EVERYONE, from the Client, to the Project Manager, the Designer, the Developers, the QA team, your friends, your family.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Test before, during and after
&lt;/h3&gt;

&lt;p&gt;Test as much as you can, run the automatic tools, take into account the manual checks and have a QA team if possible.&lt;/p&gt;

&lt;p&gt;Wait, so even though we built the site thinking of accessibility, we need to test it as well?&lt;/p&gt;

&lt;p&gt;Of course! We're not perfect, there will always be bugs, even if you don't intend to, and with a11y it's the same.&lt;/p&gt;

&lt;p&gt;Usually we design, develop and test a site as usual, and in the end someone says "hey, maybe we should check the accessibility". What happens? There are a lot of a11y issues, and since it's at the end of the project, they're harder, and more expensive to fix, so not all of them will be fixed.&lt;/p&gt;

&lt;p&gt;If we build a site thinking of a11y, and we test it all along, we'll be fixing the bugs during the design and development process, which is cheaper and faster. Although there might be some a11y bugs in the final check, there won't be a million!&lt;/p&gt;

&lt;p&gt;For instance, now I'm using Vue, so it's component based, what we're doing is checking the a11y for each component, it makes it way easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Go beyond the "100 Accessibility"
&lt;/h3&gt;

&lt;p&gt;If we pay more attention to both Lighthouse and achecker, we'll notice they both provide more information about the accessibility.&lt;/p&gt;

&lt;p&gt;In Lighthouse there's a list of items that should be manually checked. Although they don't mention anything about any of the accessibility bugs that I've listed above, they have a more detailed tutorial on how to perform these checks &lt;a href="https://developers.google.com/web/fundamentals/accessibility/how-to-review"&gt;in the link they provide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yj6huyvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/lighthouse-manual-check-list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yj6huyvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/lighthouse-manual-check-list.png" alt="alt text" title="A screenshot of the lighthouse accessibility audit with 100 score on accessibility. The first dropdown 'Additional items to manually check (10)' is extended and the items are: The page has a logical tab order, Interactive controls are keyboard focusable, Interactive elements indicate their purpose and state, The user's focus is directed to new content added to the page, User focus is not accidentally trapped in a region, Custom controls have associated labels, Custom controls have ARIA roles, Visual order on the page follows DOM order, Offscreen content is hidden from assistive technology and HTML5 landmark elements are used to improve navigation."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Something similar happens in achecker. Sure, by default they say "Congratulations! No known problems" but there are more tabs! If we go to the "Potential Problems (39)" tab we'll see that the very first potential issue they're talking about is one of our a11y bugs, the non-descriptive &lt;code&gt;alt&lt;/code&gt; in the image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yPF4lzx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/achecker-potential-problems.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yPF4lzx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/achecker-potential-problems.png" alt="alt text" title="A screenshot of the achecker accessibility audit in the 'Potencial Problems (39)' tab. Just the first problem can be seen, which is '1.1 Text Alternatives: Provide text alternatives for any non-text content', then it says 'Success Criteria 1.1.1 Non-text Content (A)' follwing the three checks: 'Check 8: img element may require a long description.', 'Check 16: Alt text is not empty and image may be decorative.' and 'Check 178: Alt text does not convey the same information as the image.' the three of them for Line 43, Column 16. For each check there is also a small screenshot of the picture and the DOM element."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there are other tools where we wouldn't have passed the automatic tests for the a11y, like the &lt;a href="https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd"&gt;axe extension for Chrome&lt;/a&gt;, which is the one that we use at Codegram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Swens7lQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/axe-a11y-report.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Swens7lQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/axe-a11y-report.png" alt="alt text" title="A screenshot of the site with the DevTools open in the axe tab that has the accessibility audit already run. The report says that the site needs a review, it found 8 issues and it also suggest 11 best practices."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ And go beyond WGAG too
&lt;/h3&gt;

&lt;p&gt;This is a quote from the book that I'm currently reading: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"people with dyslexia have a particular problem with reading justified aligned texts. It’s not clear where a line of text ends which makes it very easy to switch to the wrong line." — Better Web Typography for a Better Web, &lt;strong&gt;Matej Latin&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we resize the screen a little bit, you'll see we're failing on that too in our sample (this is because of the CSS property we've set for the body &lt;code&gt;text-align: justify;&lt;/code&gt;), and this time neither automatic tools nor WGAG have told us anything!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WF7N-26s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/justified-text.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WF7N-26s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/justified-text.png" alt="alt text" title="A screenshot of the main title of the page after you resize the window a little bit, so the text instead of being left aligned, is justified which causes the words to be really far from each other."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I'm trying to say is that there are so many things to take into account, but do not feel overwhelmed. This is just like any other topic in this profession, that you might feel like there's a lot to learn, so just like you would do with any new cutting edge technology, learn about this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read, care and learn&lt;/strong&gt; as much as you can, you will make mistakes, so will I, but we really need to care more about everyone. There are a lot of resources out there, now it's easier than ever to be an a11y superstar!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Plus, unlike the latest frontend framework, this is a safe bet, this won't be out of fashion ever!&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Follow people with special needs
&lt;/h3&gt;

&lt;p&gt;I've always been aware of a11y, and then I cared even more after that month that I had to become an "expert", because during that time I realized how many accessibility issues needed to be taken into account and they aren't most of the time.&lt;/p&gt;

&lt;p&gt;But what really helps me keep up with this topic is following people like &lt;a href="https://twitter.com/kastwey"&gt;Juanjo&lt;/a&gt; and &lt;a href="https://twitter.com/zersiax"&gt;Julian&lt;/a&gt;, blind software developers, who have to suffer all the non-accessible sites and apps.&lt;/p&gt;

&lt;p&gt;Sometimes that's been more helpful than a thousand checklists and books.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Last, but not least, A level is not an option
&lt;/h3&gt;

&lt;p&gt;Try always to aim AA level at least (and remember there's more beyond WGAG!).&lt;/p&gt;

&lt;p&gt;It will depend on the site, of course. It is not the same for a portfolio page than an official government site that every citizen will need to use eventually for some admin stuff.&lt;/p&gt;

&lt;p&gt;You'd be surprised how many sites that should be accessible, aren't: from the famous Renfe web (&lt;a href="https://twitter.com/kastwey/status/1198692536044392448"&gt;the old one&lt;/a&gt; and &lt;a href="https://twitter.com/kastwey/status/1275035878860128256"&gt;the new one&lt;/a&gt;) to the &lt;a href="https://twitter.com/kastwey/status/1298703858231894021?s=20"&gt;new Radar COVID app&lt;/a&gt;, among many others like &lt;a href="https://twitter.com/kastwey/status/1161955471168823297"&gt;McDonald's&lt;/a&gt; and even &lt;a href="https://twitter.com/kastwey/status/779463964971466753"&gt;Guardia Civil&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A final quote ✍️
&lt;/h2&gt;

&lt;p&gt;Quoting w3.org for the third time (because there's always a third!), let's never forget this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web accessibility also benefits people without disabilities, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;People using mobile phones, smart watches, smart TVs, and other devices with small screens, different input modes, etc.&lt;/li&gt;
&lt;li&gt;Older people with changing abilities due to ageing&lt;/li&gt;
&lt;li&gt;People with “temporary disabilities” such as a broken arm or lost glasses&lt;/li&gt;
&lt;li&gt;People with “situational limitations” such as in bright sunlight or in an environment where they cannot listen to audio&lt;/li&gt;
&lt;li&gt;People using a slow Internet connection, or who have limited or expensive bandwidth&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the www stands for (World Wide Web), we do live in a wide world with many different people who have many different needs. And again it is not my intention to scare you, it's just a fact that none of us is free from having a temporary or permanent need in the future, so let's try to make a more accessible web (and world) together, from people to people 💪🏻.&lt;/p&gt;

&lt;p&gt;Just remember... "&lt;a href="https://www.youtube.com/watch?v=rfU8sPLkcSE"&gt;I'll be there for you, because you will be there for me too 🎵&lt;/a&gt;".&lt;/p&gt;

&lt;h2&gt;
  
  
  #FunFact 👻
&lt;/h2&gt;

&lt;p&gt;I know what you're thinking, for real this time, I'm not talking about the form... "When is she going to talk about Comic Sans? Why the hell has she used that font?" Well, I just wanted to attract your &lt;del&gt;hate&lt;/del&gt; attention.&lt;/p&gt;

&lt;p&gt;I'm kidding, I just needed an excuse to tell you that &lt;strong&gt;Comic Sans is an accessible typeface&lt;/strong&gt;!! Did you know that? If you don't believe me, you can read this article &lt;a href="https://www.thecut.com/2020/08/the-reason-comic-sans-is-a-public-good.html"&gt;"The Reason Comic Sans Is a Public Good"&lt;/a&gt; and this other one &lt;a href="https://www.arcstone.com/blog/designing-for-accessibility-dyslexia-font-comic-sans"&gt;"Designing for accessibility: The best defense for Comic Sans"&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources 🌐
&lt;/h2&gt;

&lt;p&gt;Here are some tools and interesting links (most of them I've already mentioned), and don't worry, this won't be my last post about this topic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tools to check the accessibility:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;Lighthouse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Axe (&lt;a href="https://www.deque.com/axe/"&gt;official page&lt;/a&gt;, &lt;a href="https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd"&gt;chrome extension&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Manual Contrast Checker (&lt;a href="https://colourcontrast.cc/"&gt;official page&lt;/a&gt;, &lt;a href="https://chrome.google.com/webstore/detail/colour-contrast-checker/nmmjeclfkgjdomacpcflgdkgpphpmnfe?hl=en-GB"&gt;chrome extension&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/wcag-color-contrast-check/plnahcmalebffmaghcpcmpaciebdhgdf"&gt;Automatic Contrast Checker extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Learn more about accessibility:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.a11yproject.com/"&gt;The a11y Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/"&gt;W3C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility"&gt;MDN web docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Another interesting links:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://accessibility.blog.gov.uk/2016/09/02/dos-and-donts-on-designing-for-accessibility/"&gt;Dos and don'ts on designing for accessibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@hellokellybrito?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;J. Kelly Brito&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/checklist?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
    <item>
      <title>Peeking into Elixir - Part 1</title>
      <dc:creator>anagha vl</dc:creator>
      <pubDate>Tue, 22 Sep 2020 08:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/peeking-into-elixir-part-1-1op9</link>
      <guid>https://forem.com/codegram/peeking-into-elixir-part-1-1op9</guid>
      <description>&lt;h3&gt;
  
  
  What is Elixir and Why I wanted to learn ?
&lt;/h3&gt;

&lt;p&gt;If you don't know already, &lt;a href="https://elixir-lang.org/"&gt;Elixir&lt;/a&gt; is a dynamic, functional programming language designed for building scalable and maintainable applications. It is built on top of Erlang VM and compiles down to Erlang bytecode. Elixir has become one of the most loved programming language of recent times according to stackoverflow &lt;a href="https://insights.stackoverflow.com/survey/2019#most-loved-dreaded-and-wanted"&gt;survey&lt;/a&gt; making this more exciting.&lt;/p&gt;

&lt;p&gt;Functional programming was something that I knew by definition and the idea of using it practically sounded super fun! I did hear that I'd have to "unlearn" a bunch of things to pick up elixir, but another way to look at it would be to learn a new way of thinking about problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QAha8clq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/lets-get-started.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QAha8clq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/lets-get-started.png" alt="start-meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Shell
&lt;/h3&gt;

&lt;p&gt;Once elixir is &lt;a href="https://elixir-lang.org/install.html"&gt;installed&lt;/a&gt;, we can use &lt;code&gt;Elixir's interactive shell&lt;/code&gt; which you can start by typing &lt;code&gt;iex&lt;/code&gt; in the terminal. Here, you can experiment with Elixir expressions and get results. IEX also provides a bunch of helpers which you can access by typing &lt;code&gt;h()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a look at some features of Elixir now.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pattern Matching and Immutability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So, where I come from when we use &lt;code&gt;=&lt;/code&gt; it's to assign a certain value to a variable. But now, where we're going this means something different. The operator performs something called &lt;code&gt;pattern matching&lt;/code&gt; and hence called &lt;code&gt;match&lt;/code&gt; operator. Here, like the name suggests both elements are compared to see if they match and if they do, the right side value is bound to the left side element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#In OOP, this assigns value 10 to the variable a
a = 10 

#In Elixir, value 10 is bound to a
iex&amp;gt; a = 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fc0_PNqL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/same.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fc0_PNqL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/same.png" alt="same-meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, hold on. What if now I reverse the expression and play around with it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#In OOP, we get a syntax error
10 = a

#In Elixir, this is valid since both the sides match
iex&amp;gt; 10 = a
10

#This will throw a match error
iex&amp;gt; 11 = a
** (MatchError) no match of right hand side value: 10

#Here, a is rebound with 11
iex&amp;gt; a = 11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's try this on more complex elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Here, a = 1, b = 2, c = 3
iex&amp;gt; [a, b, c] = [1, 2, 3] 

#Here, head = 1 and tail = [2, 3]
iex&amp;gt; [head | tail] = [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the above example we were able to break the array into seperate elements. This is referred to as &lt;code&gt;destructuring&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Now that we have that cleared up, let's try to figure out what &lt;code&gt;immutability&lt;/code&gt; is. In Elixir all values are &lt;code&gt;immutable&lt;/code&gt;. When a variable once references some value it will always reference that value until it is discarded or gets garbage collected (which is actually fast here since we use different processes with its own heap). Any function that transforms this data will return a new copy of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D9k8LNMu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/wut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D9k8LNMu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/wut.png" alt="wut-meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eeesh, yeah, that was a lot. Let's break it down. Consider the following snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex&amp;gt; list1 = [3, 2, 1]

iex&amp;gt; list2 = [4 | list1]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, we'd normally expect &lt;code&gt;list2 = [4, 3, 2, 1]&lt;/code&gt; where the value of list1 ie. [3, 2, 1] is copied into the list along with 4. But since we know that value of list1 will never change, list2 is now a new list with head as 4 and tail as list1.Another thing to know about lists in Elixir is that they're implemented as Linked Lists. This means that accessing the list length is an operation that will run in linear time (O(n)). For this reason, it is typically faster to prepend than to append.&lt;/p&gt;

&lt;p&gt;Now that this makes a lot more sense, we can move on to writing functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions and Modules
&lt;/h3&gt;

&lt;p&gt;Elixir is a functional programming language that makes functions the basic type. There are no classes here to bring structure to your program, we'll have to use &lt;code&gt;functions&lt;/code&gt; and organize them into &lt;code&gt;modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Modules basically provide namespaces for things we define. We can also have multiple functions inside a single module which we can reference from outside the module using the module's name as prefix.&lt;/p&gt;

&lt;p&gt;Let's consider the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Operations.exs**

defmodule Operations do
  def sum(a, b) do
    a + b
  end
  def sum(a, b, c) do
    a + b + c
  end
end
IO.puts Operations.sum(1, 2, 3)
IO.puts Operations.sum(3, 1)

# We run the program using the command
elixir math.exs
6
4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see above, we were able to use &lt;code&gt;mutli-clause functions&lt;/code&gt;, as in have multiple definitions for the same function depending on what arguments are passed into it. The notation &lt;code&gt;function_name/number_of_arguments(arity)&lt;/code&gt; is used to represent functions. In the above example, sum/2 and sum/3 are totally separate functions as far as elixir is concerned.&lt;/p&gt;

&lt;p&gt;Although this does allow us to invoke functions based on the number of arguments passed, let's look at what we have to do to distinguish based on arguments types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guard Clauses
&lt;/h3&gt;

&lt;p&gt;These are predicates that we add to the function definition using one or more when keywords. Elixir now matches the number of arguments and then evaluates any when predicates, executing the function only if at least one predicate is true.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule Guard do
  def what_is(x) when is_number(x) do
  IO.puts "#{x} is a number"
  end
  def what_is(x) when is_list(x) do
    IO.puts "#{inspect(x)} is a list"
  end”
end

Guard.what_is(100)
100 is a number
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Recursion
&lt;/h3&gt;

&lt;p&gt;Let's take a look at the following snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for(i=0; i&amp;lt;5; i++) {
    console.log("This violates immutability")
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As the message suggests, this violates the concept of immutability because we try to mutate the variable &lt;code&gt;i&lt;/code&gt; . This iteration can be achieved in Elixir using &lt;code&gt;recursion&lt;/code&gt; which we can learn about when we write functions.&lt;/p&gt;

&lt;p&gt;Looking back at &lt;code&gt;for&lt;/code&gt; loop earlier and knowing how to write functions and guard clauses, we can write a similar piece of code this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule Recursion do
  def print_multiple_times(msg, n) when n &amp;lt;= 1 do
    IO.puts msg
  end

  def print_multiple_times(msg, n) do
    IO.puts msg
    print_multiple_times(msg, n - 1)
  end
end

Recursion.print_multiple_times("This Works!", 3)
# This Works!
# This Works!
# This Works!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, when the function is first called, failing the guard clause &lt;code&gt;n&amp;lt;=1&lt;/code&gt; (since n = 3) the second function is executed. The second one in-turn calls itself and the first function respectively after decrementing the value of n.This is pretty much how iteration is taken care of using recursion.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pipe Operator |&amp;gt;
&lt;/h3&gt;

&lt;p&gt;There have been instances where we need output of a particular function as an input to another which we wrote like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output_1 = function_1(input_1)
output_2 = function_2(output_1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using the pipe operator we can rewrite this so we take the result of the first function as the input for the second function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output2 = input_1 |&amp;gt; function_1 |&amp;gt; function_2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There's so much more to functions and modules which you can read about &lt;a href="https://elixir-lang.org/getting-started/modules-and-functions.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u6tTgSVp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/you-know-you-want-to.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u6tTgSVp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/peeking-into-elixir-part-one/you-know-you-want-to.png" alt="you-know-you-want-to-meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well so far, I must say it has been fun and I can't wait to dig deeper. Stay tuned for part 2 :")&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@marcus_wallis?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Marcus Wallis&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>But Lighthouse says I'm accessible! · Part 1</title>
      <dc:creator>Verónica Ojeda</dc:creator>
      <pubDate>Mon, 21 Sep 2020 11:37:03 +0000</pubDate>
      <link>https://forem.com/codegram/but-lighthouse-says-i-m-accessible-part-1-4h67</link>
      <guid>https://forem.com/codegram/but-lighthouse-says-i-m-accessible-part-1-4h67</guid>
      <description>&lt;p&gt;Once upon a time I was a Quality Assurance Engineer and we had a project that needed to pass &lt;em&gt;WCAG&lt;/em&gt; AA level in accessibility. But none of us had done accessibility testing before so they gave me one month to become an "expert" in accessibility. Guess what? I didn't become an expert, but I did learn a lot about it and how the automatic tools are super useful but still not enough.&lt;/p&gt;

&lt;p&gt;Now I'm on the other side of the coin, I'm a developer, and developers tend to check the accessibility with automatic tools only (if it's checked at all).&lt;/p&gt;

&lt;p&gt;Today I'm going to show you how we can pass all the automatic checks for accessibility but still not having an accessible site (and how to fix it, of course!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick intro 👋🏻
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is accessibility (or a11y)?
&lt;/h3&gt;

&lt;p&gt;Since there are so many definitions on the web, I'm going to quote one of my favorites &lt;a href="https://www.w3.org/WAI/fundamentals/accessibility-intro/"&gt;from w3.org&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web accessibility means that websites, tools, and technologies are designed and developed so that people with disabilities can use them. More specifically, people can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perceive, understand, navigate, and interact with the Web&lt;/li&gt;
&lt;li&gt;Contribute to the Web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Web accessibility encompasses all disabilities that affect access to the Web, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auditory&lt;/li&gt;
&lt;li&gt;Cognitive&lt;/li&gt;
&lt;li&gt;Neurological&lt;/li&gt;
&lt;li&gt;Physical&lt;/li&gt;
&lt;li&gt;Speech&lt;/li&gt;
&lt;li&gt;Visual&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  WCAG Levels
&lt;/h3&gt;

&lt;p&gt;I'm going to do it again, and &lt;a href="https://www.w3.org/WAI/WCAG2A-Conformance.html"&gt;quote the same web&lt;/a&gt; (sorry):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web Content Accessibility Guidelines (WCAG) explains how to make web content more accessible to people with disabilities. WCAG covers web sites, applications, and other digital content. It is developed by the World Wide Web Consortium (W3C) Web Accessibility Initiative (WAI). WCAG is an international standard.&lt;/p&gt;

&lt;p&gt;There are three levels of conformance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level A is the minimum level.&lt;/li&gt;
&lt;li&gt;Level AA includes all Level A and AA requirements. Many organizations strive to meet Level AA.&lt;/li&gt;
&lt;li&gt;Level AAA includes all Level A, AA, and AAA requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It's building time! 👷‍♀️
&lt;/h2&gt;

&lt;p&gt;Enough quoting, let's get our hands dirty!&lt;/p&gt;

&lt;p&gt;I hope you don't mind, but I've asked some Friends to help me build my cheeky and &lt;em&gt;falsy&lt;/em&gt; accessible site, it's quite ugly I know, but it's still useful for the purpose of this post.&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"es"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
         &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
         &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"&lt;/span&gt;
         &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"&lt;/span&gt;
         &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;
         &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Friends&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&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="s2"&gt;'Comic Sans MS'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;justify&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="nc"&gt;.form-control&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="nc"&gt;.form-control&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;-webkit-box-shadow&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="nl"&gt;box-shadow&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="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jumbotron jumbotron-fluid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"display-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               Let's talk about &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;F&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-danger"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;R&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-warning"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;I&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;E&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-danger"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;N&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-warning"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;D&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;·&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;S&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lead"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               Because of reasons.
            &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding-bottom: 32px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-lg-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Meet the team 👋&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;As you can see in the picture below, these are the people that are going to help us building the webpage, do you like their names?&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
                  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img img-thumbnail rounded"&lt;/span&gt;
                  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://usercontent1.hubstatic.com/12527974.jpg"&lt;/span&gt;
                  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"friends"&lt;/span&gt;
                  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
                  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-lg-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Did you hear that? 👂&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;You need to pay attention to the lyrics!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"song"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://open.spotify.com/embed/track/15tHagkk8z306XkyOHqiip"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"380"&lt;/span&gt; &lt;span class="na"&gt;frameborder=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;allowtransparency=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allow=&lt;/span&gt;&lt;span class="s"&gt;"encrypted-media"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding-top: 32px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Do you wanna develop an app? Puh rum pum pow! I'm the Devil, what should I do when I fail? Give myself an ice cream? Hmmm, human music.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Flip the pickle over. You little monster! I thought you were masturbating! Must… continue… moving… in… ways… that… lead… to… dying… with… you. You can run, but you can't hide bitch!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nice one, Ms Pancakes. What, cover me in gasoline and spiders? Fine, yeah, I'm in. Uh ohhh! Somersault jump! Aw, c'mon Rick. That doesn't seem so bad.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This aftershave made women want me, but it also made me impotent! Listen, Morty, I hate to break it to you but what people call "love" is just a chemical reaction that compels animals to breed. It hits hard, Morty, then it slowly fades, leaving you stranded in a failing marriage. I did it. Your parents are gonna do it. Break the cycle, Morty. Rise above. Focus on science. It probably has space aids. Must… continue… moving… in… ways… that… lead… to… dying… with… you.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding-top: 32px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-lg-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;h4&amp;gt;&lt;/span&gt;If you like this page, please fill in the following form which will literally do nothing 😅&lt;span class="nt"&gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"city"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;City&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"city"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"nothing"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"state"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;State&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"state"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"zip"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Zip&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zip"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"do"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-row"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding-top: 16px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"alert('I told you I did nothing!')"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-dark"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding-top: 32px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-lg-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;And last, but not least... learn some French with Joey 🇫🇷&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt;
                  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"episode fragment"&lt;/span&gt;
                  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"560"&lt;/span&gt;
                  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"315"&lt;/span&gt;
                  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.youtube.com/embed/DqwzvtjeYBQ"&lt;/span&gt;
                  &lt;span class="na"&gt;frameborder=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
                  &lt;span class="na"&gt;allow=&lt;/span&gt;&lt;span class="s"&gt;"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"&lt;/span&gt;
                  &lt;span class="na"&gt;allowfullscreen&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know exactly what you're thinking. What an ugly form, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  It's play time! 🎮
&lt;/h2&gt;

&lt;p&gt;Now that we have our super beautiful and accessible site, let's run some automatic tools to check if we've accomplished the accessibility requirements.&lt;/p&gt;

&lt;p&gt;But first, we need to serve it locally in order to run those tools. So let's use &lt;a href="https://www.npmjs.com/package/http-server"&gt;http-server&lt;/a&gt; which is quite simple, just go to your project's folder where your &lt;code&gt;index.html&lt;/code&gt; file is and run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We're ready to go, let's run Lighthouse to make sure it it's accessible indeed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open the DevTools and go to the Lighthouse tab&lt;/li&gt;
&lt;li&gt;Make sure the 'accessibility' checkbox is ticked and click on 'Generate report' (actually it's even better if you uncheck the rest of them so it is way faster)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UMUQ88W1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/lighthouse-a11y-audit-screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UMUQ88W1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/lighthouse-a11y-audit-screenshot.png" alt="alt text" title="A screenshot of the lighthouse accessibility audit where you can see we've scored 100 out of 100 in a big green circle."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yay! we did it! 🥳 Wait... but, did we? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  But Lighthouse says I am accessible! 😢
&lt;/h2&gt;

&lt;p&gt;And not only Lighthouse, if we take our site and try to run other automatic tools that check the accessibility, we would find out that the results are quite similar.&lt;/p&gt;

&lt;p&gt;Let's double check in &lt;a href="https://achecker.ca/checker/index.php"&gt;achecker&lt;/a&gt; where you upload a file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uUo0epwI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/achecker-a11y-audit-screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uUo0epwI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/but-lighthouse-says-i-am-accessible/achecker-a11y-audit-screenshot.png" alt="alt text" title="A screenshot of the achecker accessibility audit that says in a big green font 'Congratulations! No known problems' under the 'Known Problems' tab. There are other four tabs, 'Likely Problems' with no problems, 'Potential Problems' with 39 results, 'HTML Validation' and 'CSS validation' with no problems either of them. Above the tabs it also says that the accessibility reviews performed follow the WCAG 2.0 (Level AA) guidelines. Below that score there are three dropdowns: 'Additional items to manually check (10)', 'Passed audits (11)' and 'Not applicable (30)'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try to play a game and go back to our html file and try to spot as many accessibility bugs as you can in 1 minute (I'm like &lt;a href="https://youtu.be/D4zEqse0F2o?t=76"&gt;Monica in Friends when it comes to create fun games at parties&lt;/a&gt;, &lt;a href="https://media.giphy.com/media/zcMpjgfqZo0Le/source.gif"&gt;I know right&lt;/a&gt;?).&lt;/p&gt;

&lt;p&gt;Or you can cheat and just keep reading because I'm going to list them below.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1.1 Non-text Content - Level A
&lt;/h3&gt;

&lt;p&gt;We have a non-decorative image that even though it has an &lt;code&gt;alt&lt;/code&gt; description, it is not descriptive enough.&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;class=&lt;/span&gt;&lt;span class="s"&gt;"img img-thumbnail rounded"&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://usercontent1.hubstatic.com/12527974.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"friends"&lt;/span&gt;
    &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;""&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;Just the paragraph above is asking the users what they think about the character names, and they are only displayed in the picture. This can be solved either by adding the names to the paragraph per se or by adding them to the &lt;code&gt;alt&lt;/code&gt; description, e.g:&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;class=&lt;/span&gt;&lt;span class="s"&gt;"img img-thumbnail rounded"&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://usercontent1.hubstatic.com/12527974.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Picture of all the Friends characters divided in two rows and three colums, and the rows are separated by the 'FRIENDS' title. Each character is holding their name in a sign. In the first row from left to right we have Ross, Joey and Monica, in the second row Chandler, Rachel and Phoebe."&lt;/span&gt;
    &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2.1 Audio-only and Video-only (Prerecorded) - Level A
&lt;/h3&gt;

&lt;p&gt;We have a video that promise us to learn French with Joey and that's the only way to learn French in our page. We haven't given any alternative resources for that video, like a transcript, or  another video with captions.&lt;/p&gt;

&lt;p&gt;Something similar happens with the audio for the Friends theme song. We should have added the lyrics in plain text or at least a link with the lyrics&lt;/p&gt;

&lt;p&gt;In both cases, people with hearing impairment wouldn't be able to use our whole content of the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4.2 Page Titled - Level A
&lt;/h3&gt;

&lt;p&gt;Okay we do have a title, we've set &lt;code&gt;&amp;lt;title&amp;gt;Friends&amp;lt;/title&amp;gt;&lt;/code&gt;, but the purpose of the page title is to say where we are.&lt;/p&gt;

&lt;p&gt;Where are we? In the Home page? In the Contacts page? "Friends" talks about the content which is good but "Home - Friends" would have been even better.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4.7 Focus Visible - Level AA
&lt;/h3&gt;

&lt;p&gt;If you try to use the keyboard to navigate through the page, you'll see that it isn't easy to tell if we're in the form or anywhere else on the page. If it's difficult for people without problem visions, it's impossible for people who suffer them.&lt;/p&gt;

&lt;p&gt;It's because of this part of the CSS. We should remove it.&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;.form-control&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="nc"&gt;.form-control&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-box-shadow&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="nl"&gt;box-shadow&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.1.1 Language of Page - Level A
&lt;/h3&gt;

&lt;p&gt;We're bad people, we've set &lt;code&gt;&amp;lt;html lang="es"&amp;gt;&lt;/code&gt; but the page is in English.&lt;/p&gt;

&lt;p&gt;Blind people or people with several vision problems, use assistive technology to navigate through the page.&lt;/p&gt;

&lt;p&gt;This technology reads the content depending on the language we set, so if we don't specify the language of the page, or the different sections in case we have sections in different languages  (3.1.2 Language of Parts - Level AA) then it's impossible for them to understand a word.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is that all? 🤔
&lt;/h2&gt;

&lt;p&gt;No way! I've only picked a tiny miny of a way longer list of all the accessibility items that need to and can only be checked manually. If you want to see them all, checkout &lt;a href="https://www.a11yproject.com/checklist/"&gt;these checklists in the a11y project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next post, we'll see a few more improvements to the sample site we've built here and what can we do to improve the accessibility in all the projects we work on. 💪🏻&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@yomex4life?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Yomex Owo&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/accessibility?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
    <item>
      <title>Why you should hire a junior developer</title>
      <dc:creator>Elena Maroto</dc:creator>
      <pubDate>Thu, 03 Sep 2020 15:38:36 +0000</pubDate>
      <link>https://forem.com/codegram/why-you-should-hire-a-junior-developer-3ki4</link>
      <guid>https://forem.com/codegram/why-you-should-hire-a-junior-developer-3ki4</guid>
      <description>&lt;p&gt;If you are reading this, chances are you are either a recruiter doubting about why you should hire a junior dev, or a junior dev looking for a job and thinking "Aha, at last a post that will give me hope!". I feel your pain and I'm here with you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwc3ysjxpwebbe9xru34m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwc3ysjxpwebbe9xru34m.png" alt="A picture of Yoda saying: feel your pain I do"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, here's the thing. When you are a junior dev, whether recently graduated (from a bootcamp or other), self-taught or reconverted, it is really complicated to get a decent job. I know it first hand. I've been there. And in my case it was even more complicated because &lt;em&gt;I want it all&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;I was a junior dev looking for a remote job with flexibility... Gooood luck with that. 🍀&lt;/p&gt;

&lt;p&gt;It is hard enough to find a junior dev job, let alone looking for a remote one. Luckily for us, there's &lt;a href="https://www.codegram.com/" rel="noopener noreferrer"&gt;Codegram&lt;/a&gt;. 🎉🎉🎉&lt;/p&gt;

&lt;p&gt;About how and why a junior dev can be hired to work remotely, &lt;a href="https://www.codegram.com/blog/author/elisa-ramirez/" rel="noopener noreferrer"&gt;Elisa&lt;/a&gt; gives us her point of view &lt;a href="https://www.codegram.com/blog/my-learning-experience-in-a-fully-remote-company-as-a-junior-developer/" rel="noopener noreferrer"&gt;in this post&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;But I'm here to talk about why &lt;strong&gt;hiring a junior dev is good.&lt;/strong&gt;  Good for your business, for you as a manager or senior dev and for the poor, desperate junior dev looking for a job. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;But first things first&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's clarify something. A junior dev is not someone with knowledge in a thousand technologies, proficient in I don't know what and a thousand more requirements working for a very low salary. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's just an underpaid job.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2lubnzc0btys5pajizvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2lubnzc0btys5pajizvs.png" alt="MUST HAVE SKILLS. 3+ years of Salesforce.com/Force.com development experience (using Apex, VisualForce). Experience developing user-interfaces using HTML, Javascript and CSS. NICE TO HAVE SKILLS. 5+ years of Object Oriented Programming (Java or C#.NET) development experience. SalesForce Lightning. Experience integrating Salesforce with 3rd party systems. SalesForce.com certifications (Developer, Advanced Developer) are a big asset.Expertise and Skills. Software Development, C# .NET 2-4 years. Software Development, Java 2-4 years."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This 👆👆👆 is &lt;strong&gt;NOT&lt;/strong&gt; a junior job. And yes, this comes from a real junior dev job offer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0a9o2c1um1j7a61pihzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0a9o2c1um1j7a61pihzd.png" alt="A cute design of two puppies shaking hands and saying: Ok then, glad we cleared that up :)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By no means I am trying to say that you should only hire junior devs. In fact, that would be a disaster for your company. But hiring junior devs comes with its share of benefits.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Impressive learning curve&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The good point about being a junior is that there is so much to learn. So, there is a lot of room for improvement and the learning curve would look something like this. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz6hlffrgkql7xdmq1sly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz6hlffrgkql7xdmq1sly.png" alt="An image showing the learning curve in regards to experience. In the y axe we can read Learning, in the x axe we can read Experience. The curve is more steep when there is less experience and it flattens as experience increases."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although in development there is always so much to learn, the improvement is much more visible when you start as a junior dev, for obvious reasons. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A fresh pair of eyes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Yes, a senior has more knowledge and sometimes that's all you need in your project. An expert able to get up to speed fast. But sometimes you just need another look at it, a fresh pair of eyes. &lt;/p&gt;

&lt;p&gt;Juniors are not that biased (regarding the project, the customer, the company culture or the methodology) so they are able to ask questions or even make proposals that other more senior devs wouldn't, just because it would seem stupid or obvious to them. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sometimes the solution comes from the simplest of the proposals and that, a junior can do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, some juniors might come from other jobs and have just reconverted. Their experience in other fields can bring light and a different way of thinking to the table that can be very valuable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Get that repetitive/ungrateful tasks done&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Remember that refactoring you've been meaning to do but never had the time to? Or simply you just thought it was boring and you wouldn't learn anything new? Well, your junior dev could use some of that!&lt;/p&gt;

&lt;p&gt;Being a junior means that almost everything is new and the most boring task for a senior could be a whole new improvement field for a junior.&lt;/p&gt;

&lt;p&gt;Like, e.g. we've taken advantage of summer time and students holidays to reorganize our Graphql resolvers in &lt;a href="http://empresaula.com/" rel="noopener noreferrer"&gt;Empresaula&lt;/a&gt;. Sure, after you've done it 50 times it doesn't bring anything that new to the table, but I for sure have learnt a big deal and had to deal with many issues that I wouldn't have faced otherwise. &lt;/p&gt;

&lt;p&gt;So, it is a win-win. You get that long-awaited task done and your junior learns a lot!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F51j5qslfdjz1p98wd4bq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F51j5qslfdjz1p98wd4bq.png" alt="An image showing two hands each holding a piece of a puzzle that fit together. When the pieces fit we can read the word success."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Educate them into your company culture, methodology, etc.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If your junior is fresh-off-school, then the field is green all over. They do not have any previous experience, bias, etc. That doesn't mean they don't have an opinion, but they have less to compare to, and they are more willing to get guidance and follow procedures, etc. &lt;/p&gt;

&lt;p&gt;If your junior has reconverted, it means you have someone in your team who most likely left a stable job, maybe even a well paid job, to become a developer. They were even possibly a senior in another field. That's big. Making such a change is really difficult (I know it first hand). But it also means that this person is able and willing to adapt, to learn and to question themself. So they can not only embrace your company culture, but also bring fresh ideas to the table. That has a big value.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;It's cheaper and less risky&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As I said at the beginning of the post, a junior dev post shouldn't hide an underpaid job. I cannot stress this enough: &lt;strong&gt;Experience has to be paid&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;That's why hiring a junior dev is cheaper. In exchange, and if you want this to be rewarding, you need to invest in them. Mainly in coaching and technical training. Otherwise, you could end up with a junior forever. And nobody wants that. Not you as an employer and for sure not the developer. Every person wants to evolve in their job. Help them do it and you won't be disappointed. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of a junior dev as a longtime investment. If you take the time, interest and right approach with your junior dev, you could get yourself a very loyal, very productive employee.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What about the risks? Well, you could argue that you might educate them and they would fly away. Yes, that is a possibility. But so can your senior devs. If this happens, the effects of having a junior vs a senior leaving are way less devastating. &lt;/p&gt;

&lt;p&gt;Ultimately, it is up to you to make your employees happy so they want to stay with you. And &lt;strong&gt;happiness at work is not foosball, free coffee or casual friday.&lt;/strong&gt; There's way more to it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftryuu2zvwjkce1lp6v62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftryuu2zvwjkce1lp6v62.png" alt="A graph image representing what makes happiness at work. In the center there is a circle with the words happiness at work. There are arrows coming out of it and pointing to rectangles with different words. From the top clockwise we can read. Personality Pattern. Social Connections. Autonomy and Decision making. Financial security. Scope for innovation and creativity. Acceptance and empathy. Challenges and diversity of tasks. Work-life balance."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many other benefits to bring a junior dev to your team, but the main point of this post is to show that &lt;strong&gt;a junior is not only someone without much experience, but someone with a lot of potential.&lt;/strong&gt; And that is what you should be looking for. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The key to greatness is to look for people's potential and spend time developing it. Peter Drucker.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>Understanding Regular Expressions once and for all [PART 4]</title>
      <dc:creator>Svenja Schäfer</dc:creator>
      <pubDate>Mon, 17 Aug 2020 07:17:56 +0000</pubDate>
      <link>https://forem.com/codegram/understanding-regular-expressions-once-and-for-all-part-4-5gab</link>
      <guid>https://forem.com/codegram/understanding-regular-expressions-once-and-for-all-part-4-5gab</guid>
      <description>&lt;p&gt;Originally published at: &lt;a href="https://www.codegram.com/blog/understanding-regex-once-and-for-all-part-four/" rel="noopener noreferrer"&gt;Codegram's blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here comes part 4 of the &lt;a href="https://www.codegram.com/blog/tag/reg-ex/" rel="noopener noreferrer"&gt;&lt;strong&gt;"Understanding Regular Expressions once and for all"&lt;/strong&gt;&lt;/a&gt; series. Until now, you should be able to match literal characters, numbers, spaces at the end and beginning of a line. Also, you are aware of the optional character - the question mark. And you can check if a character appears minimum once or zero times thanks to &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt;. So far, so good. Today, it's time to meet brackets.&lt;/p&gt;

&lt;h3&gt;
  
  
  DINNER WITH [FRIENDS]
&lt;/h3&gt;

&lt;p&gt;Imagine some friends will come over for dinner. And you have to prepare the evening, including - of course - the dinner itself. You look through all the recipes but this time it's not super important what you cook (ingredients), but for how many people it is. Our task: only matching recipes for the number of friends coming over. Let's say, 5 friends will sit at the table tonight. We could write something like this: &lt;code&gt;servings: 5&lt;/code&gt;. But while this is a totally accepted expression, we want to make it a bit more "regex-like". Also, there's always this type of friend who brings someone with and another might cancel, so a range would be better suited. Ranges can look like this: &lt;code&gt;[0-3]&lt;/code&gt;. So, our expression could be: &lt;code&gt;servings:\s[4-6]&lt;/code&gt;. With this, we would match the recipes for 4, 5 and 6 people. &lt;/p&gt;

&lt;p&gt;But what if we run a nice vegan BBQ party? We expect to see about 12 - 16 people. How can we match that? Remember, that we match a single character. Always. If we want to match more, we specifically have to say it. We could end up with something like this: &lt;code&gt;servings:\s[0-9]+&lt;/code&gt; but with that, we would actually match any amount. Useless. We could, however, write this: &lt;code&gt;servings:\s[1][2-6]&lt;/code&gt;. Nice, isn't it? &lt;/p&gt;

&lt;p&gt;The square brackets also work with any other character. For example, if we want to match all recipes starting with a capital B (like the B in BBQ), we could use this expression: &lt;code&gt;^B&lt;/code&gt;, right? But what, if the recipes we are looking for are ordered under G (like in Grilling)? Easy-peasy with our square brackets: &lt;code&gt;^[BG]&lt;/code&gt;. You see, it doesn't have to be a range we are looking for. Any character inside the square brackets &lt;strong&gt;can&lt;/strong&gt; be a match. Can, not must! &lt;/p&gt;

&lt;h3&gt;
  
  
  EXCEPTIONS, EXCEPTIONS
&lt;/h3&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpvc24ntjy609nj2yxgnx.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpvc24ntjy609nj2yxgnx.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you see in the previous expression, that the caret character is outside the square brackets? That's not an error but has a good reason. If it were inside like this: &lt;code&gt;[^BG]&lt;/code&gt;, we would match any recipe that doesn't have a B or G. The &lt;code&gt;^&lt;/code&gt; inside square brackets means &lt;strong&gt;not&lt;/strong&gt;. Sure, we can use this as well. For example, like this: &lt;code&gt;^[^AC-FH-Z]&lt;/code&gt;. With that, we wouldn't match any starting uppercase letter besides B and G. To exclude any lowercase characters as well, we could change the expression into: &lt;code&gt;^[^a-zAC-FH-Z]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Yes, square brackets are pretty useful and like the rest of regular expressions powerful. But there are more. More brackets. Curly ones for example.&lt;/p&gt;

&lt;p&gt;Remember, when we covered matching &lt;strong&gt;multiple digits&lt;/strong&gt; in &lt;a href="https://www.codegram.com/blog/understanding-regex-once-and-for-all-part-three/" rel="noopener noreferrer"&gt;Part 3&lt;/a&gt; of this blog series? We used &lt;code&gt;*&lt;/code&gt; or &lt;code&gt;+&lt;/code&gt; for it. But what if we don't want to end up with endless repetitions of a character but matching a specific amount? Say hello to &lt;code&gt;{}&lt;/code&gt;. Whichever character length you want to define, this is the expression for it. So maybe we want to find all digits with the length of 4 in our recipe, like &lt;em&gt;1000 ml.&lt;/em&gt; Just because we want to change it into &lt;em&gt;1 litre&lt;/em&gt;. We could write &lt;code&gt;\d{4}&lt;/code&gt;. Even ranges are possible with these neat brackets. To match minimum four and maximum six characters, the regular expression would look like this: &lt;code&gt;\d{4,6}&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;See, with only two types of brackets, you can be so much more precise. Imagine what you can do with three types. That's exactly what we will learn in the next part. But until then:&lt;br&gt;
&lt;code&gt;^Ke{2}p\s[n-p]+\slearning$&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;Photos by &lt;a href="https://unsplash.com/@jruscello" rel="noopener noreferrer"&gt;Jessica Ruscello&lt;/a&gt; on &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>regex</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Crawling websites with elixir and crawly</title>
      <dc:creator>Codegram</dc:creator>
      <pubDate>Thu, 13 Aug 2020 12:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/crawling-websites-with-elixir-and-crawly-4p57</link>
      <guid>https://forem.com/codegram/crawling-websites-with-elixir-and-crawly-4p57</guid>
      <description>&lt;p&gt;In this post, I'd like to introduce &lt;a href="https://github.com/oltarasenko/crawly"&gt;crawly&lt;/a&gt; which is an elixir library for &lt;a href="https://en.wikipedia.org/wiki/Web_crawler"&gt;crawling&lt;/a&gt; websites.&lt;/p&gt;

&lt;p&gt;My idea for this post is to be a quick introduction to how we can use crawly. For this little example we're going to extract the latest posts titles on our website and write it to a file, so let's do it.&lt;/p&gt;

&lt;p&gt;First of all, we need elixir installed, in case you don't have it installed you can check this &lt;a href="https://elixir-lang.org/install.html"&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once we have elixir installed let's create our elixir application with built-in supervisor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix new crawler --sup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to add the crawly dependencies to our project, we are going to change the deps function in the file &lt;code&gt;mix.exs&lt;/code&gt; and it should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defp deps do
    [
        {:crawly, "~&amp;gt; 0.10.0"},
        {:floki, "~&amp;gt; 0.26.0"} # used to parse html
    ]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to install the dependencies that we just added running the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a spider file &lt;code&gt;lib/crawler/blog_spider.ex&lt;/code&gt; that is going to make a request to our blog, query the HTML response to get the post titles, and then returns a &lt;code&gt;ParsedItem&lt;/code&gt; which contains items and requests. We are not going to leave requests as an empty list to keep it simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule BlogSpider do
  use Crawly.Spider

  @impl Crawly.Spider
  def base_url(), do: "https://www.codegram.com"

  @impl Crawly.Spider
  def init(), do: [start_urls: ["https://www.codegram.com/blog"]] # urls that are going to be parsed

  @impl Crawly.Spider
  def parse_item(response) do
    {:ok, document} = Floki.parse_document(response.body)

    items =
      document
      |&amp;gt; Floki.find("h5.card-content__title") # query h5 elements with class card-content__title
      |&amp;gt; Enum.map(&amp;amp;Floki.text/1)
      |&amp;gt; Enum.map(fn title -&amp;gt; %{title: title} end)

    %Crawly.ParsedItem{items: items, requests: []}
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our spider created it would be nice to save what we're extracting into some file. To do this we can use a pipeline provided by crawly called &lt;code&gt;Crawly.Pipelines.WriteToFile&lt;/code&gt;. For that, we need a &lt;code&gt;config&lt;/code&gt; folder and a &lt;code&gt;config.exs&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir config # creates the config directory
touch config/config.exs # creates an empty file called config.exs inside the config folder
mkdir -p priv/output # creates output folder inside priv where we are going to store our files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create the configuration to save the response from our spider into a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Mix.Config

config :crawly,
  pipelines: [
    Crawly.Pipelines.JSONEncoder, # encode each item into json
    {Crawly.Pipelines.WriteToFile, folder: "priv/output/", extension: "jl"} # stores the items into a file inside the folder specified
  ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we are good to go, we can open the elixir repl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex -S mix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we can execute our spider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Crawly.Engine.start_spider(BlogSpider)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The spider is going to be executed by a supervisor and then we should see a new file inside priv/output folder. In my case the lasts posts showing in the first page are&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"title":"\"High tech, high touch\": A communication toolkit for virtual team"}
{"title":"My learning experience in a fully remote company as a Junior Developer"}
{"title":"Finding similar documents with transformers"}
{"title":"UX… What?"}
{"title":"Slice Machine from Prismic"}
{"title":"Stop (ab)using z-index"}
{"title":"Angular for Junior Backend Devs"}
{"title":"Jumping into the world of UX 🦄"}
{"title":"Gettin' jiggy wit' Git - Part 1"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just a simple example of what is possible to do using &lt;code&gt;crawly&lt;/code&gt;. I hope you enjoyed this introduction and remember to be responsible when extracting data from websites.&lt;/p&gt;

</description>
      <category>elixir</category>
    </item>
    <item>
      <title>My learning experience in a fully remote company as a Junior Developer</title>
      <dc:creator>Codegram</dc:creator>
      <pubDate>Tue, 14 Jul 2020 08:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/my-learning-experience-in-a-fully-remote-company-as-a-junior-developer-1774</link>
      <guid>https://forem.com/codegram/my-learning-experience-in-a-fully-remote-company-as-a-junior-developer-1774</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qfJLihfd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8nilqov7kfxbico6a7uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qfJLihfd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8nilqov7kfxbico6a7uc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three years ago I decided that I wanted to change my profession and look for better opportunities. I’m an Industrial Engineer and IT was, among other sectors, the one that since the beginning drew my attention the most, in particular the world of application development. I could still remember some of my development skills from my studies at university, so I decided to give it a try and start studying a language called &lt;a href="https://guides.rubyonrails.org/"&gt;Ruby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first steps were not easy, I couldn’t understand many concepts, and my English skills back then slowed down my progress. After improving my English skills and completing some courses and books and after a lot of effort and frustration, I managed to land my first job 2 years ago.&lt;/p&gt;

&lt;p&gt;Due to my personal situation I needed to find a remote job, but I would usually get the same answer: &lt;strong&gt;"with your profile you must work in the office"&lt;/strong&gt;, another unattainable job for me. &lt;/p&gt;

&lt;p&gt;I started wondering what was the difference between talking to a person next to you, or someone on the other side of the screen when they can both hear you and see your code?. My conclusion was, after speaking with experienced remote developers, that there was none… if they really want to work with you.&lt;/p&gt;

&lt;p&gt;My very first job wasn't remote, the office was located a 5-minute walk from my place and that's why I decided to give it a try, but in the end, it only lasted one month, a really long month. They didn't know how to work as a team, which led them to use strange work methodologies and management also had a weird relationship with the employees that thankfully, I never saw again. It wasn't a good place to start my professional career and I didn't have the feeling that anything that I did couldn't be done remotely, so I decided that my next job has to be fully remote no matter what.&lt;/p&gt;

&lt;p&gt;During the next months, I rejected a good number of offers, where working from home with my profile was not an option. Finally, I managed to find a company where they wanted to try remote work with juniors!&lt;/p&gt;

&lt;p&gt;It was much better than my previous experience, but it wasn't my place either. I worked for this company for more than 6 months, but we couldn’t figure out how to make it work. The company managed to sign a bunch of deals with new clients and they didn't have resources to help me to grow. I felt stuck and not performing as I would like to so we decided that it was time to move. &lt;/p&gt;

&lt;p&gt;Those first experiences didn’t help me to clearly see my future in development, but everything changed when I joined Codegram…&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Interviews&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I met the three founders, Oriol, Josep, and Txus, through 3 very pleasant and entertaining interviews that managed to get my attention for the company.&lt;/p&gt;

&lt;p&gt;I admit that it was not the first time I heard some of the things they told to me; everyone wants to teach you and help you to improve, but there is a long way between wanting to do something and doing it. Nevertheless, the way they behaved and how openly they spoke gave me more confidence than my previous interviews, so I decided to follow their hiring process. Finally, I managed to get the job! &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;My first days at Codegram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The evening before my first day of work, I was eager to get started as well as worried about what I might find in this new adventure. If it went wrong, I had lost nothing, but I wanted it to go well.&lt;/p&gt;

&lt;p&gt;The big day came and when it was over I felt I had nothing to worry about.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Day 1&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For me, the hardest thing about working remotely is the feeling of being alone in front of something unknown. When I start a new job, a feeling of being lost usually invades me and the days turn into a research job. This time I had my new computer ready to start working, and in my email a document with the first tasks to be performed within the company, in addition to the name of the person who was going to help me whenever I needed it, that seemed like a dream!&lt;/p&gt;

&lt;p&gt;Having a reference person, Arnau in my case, is very useful. Of course, there are other people I can ask for help, but, especially at the beginning, I didn't know who was the right person for different topics, or if they have a high workload and you are bothering them. In addition to this, the existence of a person who knows your defects and your strengths at work can help you to learn faster. Something I did not expect that day was a meeting with Josep and Oriol, to find out how my day had gone, it was the first time that a C-Level cared about how I felt at work. In this sector, it is very important to know if the people in your company are happy. I have know companies that have suffered massive developer losses, with the risk that this entails for their own existence.&lt;/p&gt;

&lt;p&gt;The first day of work gives you a fairly accurate idea of what your day to day will be like and my day ended with a desire to learn more.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;My first months&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In my day to day, there are many concepts that I do not know, and my big problem when learning as a Junior is having too many open fronts and not knowing what I should study.&lt;/p&gt;

&lt;p&gt;As I discover this world I am more aware of how vast it is and of everything that I do not know, which is really overwhelming, that is why I need an easy goal to achieve so as not to block myself and continue learning. I have different meetings in which I explain what I would like to improve or what is a problem for me, and in this way, I can direct my work and my learning in the same direction.&lt;/p&gt;

&lt;p&gt;Currently, my job is to fix small bugs or add small features, without the obligation to be productive from day one, it helps me to discover new concepts and acquiring better practices in my day to day, such as learning to research, debug or manage repositories with agility.&lt;/p&gt;

&lt;p&gt;One of the most efficient ways of learning is to alternate studying something new by working on what you have learned, for which I have 5 hours each week to study whatever interests me. Also, every 2 weeks we enjoy listening to our colleagues talk about an interesting topic, what better way to discover something new than when someone explains it to you from their own experience!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Nowadays&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After 4 months I am still curious to know how much I will be able to grow here, I am learning new things and improving my coding speed, although not as fast as I would like. &lt;/p&gt;

&lt;p&gt;After this experience, I no longer doubt my future as a developer.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Lessons learned&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is what I have learned from my experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;It is possible to work as a junior remotely&lt;/em&gt;&lt;/strong&gt; if the company is willing to help you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Having a dedicated mentor&lt;/em&gt;&lt;/strong&gt; you can turn to at any time increases your learning speed and reduces downtime.&lt;/li&gt;
&lt;li&gt;Carrying out &lt;strong&gt;&lt;em&gt;small tasks makes you aware of your strengths and weaknesses&lt;/em&gt;&lt;/strong&gt;, letting you establish a more targeted training plan.&lt;/li&gt;
&lt;li&gt;To learn at a higher speed, &lt;strong&gt;&lt;em&gt;it is important not to have the obligation to be productive at the beginning&lt;/em&gt;&lt;/strong&gt;, since that only frustrates you. It is more important to acquire a stable knowledge base to gain more speed over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;A disgruntled worker does not learn&lt;/em&gt;&lt;/strong&gt;, or does so at a reduced speed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, remote work can be facilitated and also help improve your career plan, provided you are lucky enough to find a company willing to make it possible.&lt;/p&gt;

&lt;p&gt;📌 Codegram is always looking for great talents. Visit our &lt;a href="https://www.codegram.com/careers/"&gt;career page&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@vrsh"&gt;Veronika Hradilová&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>junior</category>
      <category>remote</category>
    </item>
    <item>
      <title>Fighting impostor syndrome in four easy steps</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Mon, 13 Jul 2020 08:16:37 +0000</pubDate>
      <link>https://forem.com/codegram/fighting-impostor-syndrome-in-four-easy-steps-4doe</link>
      <guid>https://forem.com/codegram/fighting-impostor-syndrome-in-four-easy-steps-4doe</guid>
      <description>&lt;p&gt;If you are anything like me, you have experienced impostor syndrome at some point in your life. If you are really like me, you have to deal with it pretty often. And we both know that sucks. So, for this week's lunch talks, let's try and get rid of it once and for all! *&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* Ok, let's be honest. It probably won't work 100%. But if we can reduce it a teeny-weeny bit, we'll have succeeded&lt;/em&gt; 🙌&lt;/p&gt;

&lt;h3&gt;
  
  
  What makes a developer? | Ivana McConnell &lt;em&gt;(29:33 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;First, repeat with me: "I &lt;strong&gt;am&lt;/strong&gt; a developer". No matter where your background is, no matter what languages you know. Ivana McConnell insists on that, and puts focus on consciously pull away from perceptions that devaluate certain languages or paths into development. It's not you, it's them. You &lt;strong&gt;are&lt;/strong&gt; a developer.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Attitude Determines Altitude: Engineering Yourself &amp;amp; Your Teams | Randy Shoup &lt;em&gt;(43:02 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Ok, you now believe you are a developer. Great! But, I know, it's not easy to keep the confidence up. Randy Shoup focuses on the psychological aspects of how our mind works and talks about getting into a growth mindset and gaining trust and confidence.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Mejorando como desarrolladores | Belén Albeza &lt;em&gt;(42:24 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Hopefully confidence is building up on you, and you want to keep improving as a developer. But, what to learn next? Many new shiny things come up every day, and it's hard to know what to focus on. Belén Albeza gives us concrete advice (in Spanish) on what to do to keep learning effectively, and how we can make our teammates better as well.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Why you should make useless things | Simone Giertz &lt;em&gt;(11:58 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Yay! You are a confident developer and you know how to keep improving. What's next? It's likely your career will be bumpy, and you will fail a lot, but that's ok because you will succeed on other things too. You don't need to build a rocket and save the human race by terraforming Mars to be a great developer. Simone Giertz talks about the importance of making useless things, how it will relieve you from pressure and how it can lead to unexpectedly awesome results. Plus, she is wearing a googly eyes t-shirt.&lt;/p&gt;

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

</description>
      <category>motivation</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Slice Machine from Prismic</title>
      <dc:creator>Anna Collins</dc:creator>
      <pubDate>Mon, 29 Jun 2020 08:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/slice-machine-from-prismic-2k27</link>
      <guid>https://forem.com/codegram/slice-machine-from-prismic-2k27</guid>
      <description>&lt;p&gt;In May my colleagues &lt;a href="https://www.codegram.com/blog/author/aitor-porro/"&gt;Aitor&lt;/a&gt;, &lt;a href="https://www.codegram.com/blog/author/nuria-soriano/"&gt;Núria&lt;/a&gt; and I attended our first virtual conference, &lt;a href="https://jamstackconf.com/virtual/"&gt;Jamstack Conf&lt;/a&gt;. Check out Núria's blogpost &lt;a href="https://www.codegram.com/blog/jamstack-conf-a-virtual-conference-experience"&gt;here&lt;/a&gt; on the virtual conference experience! Amongst other talks was a lightning talk by Renaud Bressand, a project manager at &lt;a href="https://prismic.io/"&gt;Prismic&lt;/a&gt;. If you don't know, Prismic is a CMS. We often use it in our JAMStack projects at Codegram so we were super interested to hear what they had to say. Prismic announced in the talk the release of their new open source project &lt;a href="https://www.slicemachine.dev/"&gt;Slice Machine&lt;/a&gt;! Well it sounds pretty cool, right? Let's take a look at what exactly it can do for us.&lt;/p&gt;

&lt;p&gt;So as I said, Prismic is a CMS where we can handle content for our websites. To look at a simple example, we could take an entry for a news article. We might know that every article has a title, a headline and a main image so we can add those fields to the article content type in Prismic, but what about the rest of the article? We don't want to restrict the editor to stick to a rigid predefined template. And we want to make the editing experience as visual and intuitive as possible. That's where Prismic slices come in. Enter Slice Zone...&lt;/p&gt;

&lt;p&gt;Slice Zone is a section you can add to your content types to give the editor more freedom when entering content. You are able to define a number of different content types which the user can then select from, in the order they wish. Let's take our example of a news article. Maybe a news article can be composed of: text, images, quotes, videos, subtitles, tweets, CTAs etc. Slice zone lets the user select the types and input content in the order they wish.&lt;/p&gt;

&lt;p&gt;So that's Slice Zone, what about Slice Machine? Slice Machine takes Slice Zone to the next level by making it super easy for editors to build pages made up of component sections without any help from developers. Prismic describe it as "In it’s most basic form, Slice Machine is an open-source CLI and a component library". Let's see how it works.&lt;/p&gt;

&lt;p&gt;First of all we need to install the Prismic CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; prismic-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Currently Slice Machine is only available for Nuxt.js projects, so we'll also need to create one of those&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx create-nuxt-app annas-slice-machine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now from inside the project, run the Slice Machine setup command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;prismic sm &lt;span class="nt"&gt;--setup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will connect the default component library and add dependencies (you will see these extra configurations added to your &lt;code&gt;nuxt.config.js&lt;/code&gt; file along with a &lt;code&gt;sm.json&lt;/code&gt; file). This command will ask you to login to an existing Prismic account or to create a new one and will create a new repository in the account with a standard "Page" custom type for starting out.&lt;/p&gt;

&lt;p&gt;You can add the Slice Zone to an existing page but here we're going to create a new page &lt;code&gt;_uid.vue&lt;/code&gt; with the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;slice-zone&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt; &lt;span class="na"&gt;:uid=&lt;/span&gt;&lt;span class="s"&gt;"$route.params.uid"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SliceZone&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-slicezone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;SliceZone&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The Slice Zone component has two props here, the &lt;code&gt;type&lt;/code&gt;, which at the moment we only have the &lt;code&gt;page&lt;/code&gt; type that comes out of the box, and &lt;code&gt;uid&lt;/code&gt; which is the unique identifier for the page and will be the name of the route.&lt;/p&gt;

&lt;p&gt;In your newly created Prismic repository add a new &lt;code&gt;page&lt;/code&gt; type. You'll see here the Slice Zone and all the possible premade components you can add to your page. You can go on over to the &lt;a href="https://vue-essential-slices.netlify.app/?path=/story/introduction-%F0%9F%91%8B--wip"&gt;storybook&lt;/a&gt; to see what these components look like. They've been created by &lt;a href="https://twitter.com/SaraSoueidan"&gt;Sara Soueidan&lt;/a&gt; and are accessible and responsive too!&lt;/p&gt;

&lt;p&gt;Once you've added a &lt;code&gt;uid&lt;/code&gt; and a slice for your page, you can run &lt;code&gt;npm run dev&lt;/code&gt; and go over to &lt;code&gt;[localhost:3000/uid-of-page](http://localhost:3000/uid-of-page)&lt;/code&gt; and see that a page has been created with the route of the &lt;code&gt;uid&lt;/code&gt; you just added in Prismic. That was easy peasy right!?&lt;/p&gt;

&lt;p&gt;So you might be thinking it's cool, but that you need more control over the design of your page. Well Slice Machine provides ways to customise the default library by using &lt;a href="https://www.slicemachine.dev/documentation/customization#themes"&gt;themes&lt;/a&gt;, allowing you to make small changes such as colors and text align. But better than this, it also allows you to easily create your own custom slices via the CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;prismic sm &lt;span class="nt"&gt;--create-slice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will prompt you to provide the name of your slice, and the custom types that you want this slice to be available, for example the page type, which is currently the only type we have.&lt;/p&gt;

&lt;p&gt;In your project a new folder &lt;code&gt;slices&lt;/code&gt; will have been created and inside that a folder with the name of your new component containing two files, &lt;code&gt;index.vue&lt;/code&gt; and &lt;code&gt;model.json&lt;/code&gt;. Your new slice will also appear in the Slice Zone for the page type where you can update and add/remove entries from it via the Prismic dashboard. Due to still being in beta, you will need to update the &lt;code&gt;model.json&lt;/code&gt; file manually but Prismic say they are working on a Custom Types API where you will be able to send custom types to the repo with a CURL request 🎉&lt;/p&gt;

&lt;p&gt;We've only scratched the surface but I think Slice Machine could be a great tool for making developers lives easier and for giving more freedom and control to editors with JAMStack websites!&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>cms</category>
      <category>prismic</category>
    </item>
  </channel>
</rss>
