<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lars</title>
    <description>The latest articles on DEV Community by Lars (@codetraveling).</description>
    <link>https://dev.to/codetraveling</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F378576%2Fb8918f3d-dc22-4bf2-8087-2e57c1223333.jpg</url>
      <title>DEV Community: Lars</title>
      <link>https://dev.to/codetraveling</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codetraveling"/>
    <language>en</language>
    <item>
      <title>The Definitive Guide to Netlify Serverless Functions</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 05 Mar 2021 10:13:48 +0000</pubDate>
      <link>https://dev.to/codetraveling/the-definitive-guide-to-netlify-serverless-functions-3p5o</link>
      <guid>https://dev.to/codetraveling/the-definitive-guide-to-netlify-serverless-functions-3p5o</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo&lt;/strong&gt; (&lt;a href="https://gatsby-with-netlify-functions.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) | &lt;strong&gt;Repo&lt;/strong&gt; (&lt;a href="https://github.com/LarsBehrenberg/gatsby-with-netlify-functions" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;With the rise of the JAMStack and the serverless approach, most of the things that used to require a backend are now handled completely on the front-end or through APIs. &lt;strong&gt;But sometimes this is not enough, and that's where "serverless functions" come in.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Let's go and have a look at it. &lt;strong&gt;What are some use cases for serverless functions and how do you set them up?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Quick note: There are many different providers to run your serverless functions like AWS Lamda, Azure Functions, or Google Functions. However, in this tutorial, we will be using Netlify as it offers one of the most user-friendly experiences to set up and run your environment.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; What are serverless functions? &lt;/li&gt;
&lt;li&gt; What can you do with serverless functions? &lt;/li&gt;
&lt;li&gt; Getting started with Netlify Functions 

&lt;ul&gt;
&lt;li&gt; Prerequisites &lt;/li&gt;
&lt;li&gt; Set up your folder structure &lt;/li&gt;
&lt;li&gt; Create a serverless function &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt; Trigger a serverless function and receive a response &lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are serverless functions?
&lt;/h2&gt;

&lt;p&gt;One thing to get right from the start, "serverless" can be a little bit misleading, as a server is needed to execute your functions. A good way to think about it is that back in the day you needed to spin up your own server, maintain it and pay for it 24/7 to run any functions. &lt;/p&gt;

&lt;p&gt;However, now with the "serverless" option, this has changed &lt;strong&gt;to a "pay as you go"-approach, meaning on-demand computing&lt;/strong&gt;. Pay a provider like Netlify, for each execution of your functions and not a server in general. &lt;/p&gt;

&lt;p&gt;Another main advantage of this is that &lt;strong&gt;you don't need to worry about your server infrastructure anymore&lt;/strong&gt; and whether everything will be fine if you have a sudden increase in users. &lt;/p&gt;

&lt;p&gt;Scaling your applications has just become a lot easier.&lt;/p&gt;

&lt;p&gt;Serverless functions are the missing piece in the serverless approach of the JAMStack. It allows you to integrate any missing features that you couldn't handle with statically rendered pages. &lt;/p&gt;

&lt;h2&gt;
  
  
  What can you do with serverless functions?
&lt;/h2&gt;

&lt;p&gt;Here is a list of a few of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Talk to any API&lt;/li&gt;
&lt;li&gt;Run Data/Image processing&lt;/li&gt;
&lt;li&gt;Utilize user authentication&lt;/li&gt;
&lt;li&gt;Integrate 3rd party services (Ecommerce, etc.)&lt;/li&gt;
&lt;li&gt;Send Emails&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This enables us to do a variety of things! &lt;strong&gt;So let's have a look at what we need to get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with Neltlify Functions
&lt;/h2&gt;

&lt;p&gt;Netlify has put a lot of effort into making the deployment process on their platform one of the easiest out there. You can either get started with one of the &lt;a href="https://functions.netlify.com/examples/" rel="noopener noreferrer"&gt;many example repos&lt;/a&gt; that Netlify has put together for you or you read further below to learn how to set up Netlify's Serverless Functions in your project on your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;First, we want to install the Neltify CLI. This will allow us to test our serverless functions locally instead of having to deploy every time we make a change. If you don't have it installed yet:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up your folder structure
&lt;/h3&gt;

&lt;p&gt;To get started all you need to do is configure a folder with all your functions inside and that folder will automatically be exposed as a web endpoint under the site-relative path. The default is &lt;code&gt;netlify/functions/&lt;/code&gt;. But you can simply change that by going into the Netlify web interface under "Deploy Settings". Or create a Netlify configuration file ( &lt;code&gt;netlify.toml&lt;/code&gt;) in your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;[build]
  functions = "serverless_functions"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find more details on the topic &lt;a href="https://docs.netlify.com/functions/configure-and-deploy/#configure-the-functions-folder" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a serverless function
&lt;/h3&gt;

&lt;p&gt;Next up, we want to create a function in our functions directory. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;serverless_functions/fetch-weather.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;serverless_functions/stripe-payments.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;serverless_functions/handle-user-input.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These will later be available relative to the base URL of your site at: &lt;code&gt;/.netlify/functions/fetch-weather&lt;/code&gt; or &lt;code&gt;/.netlify/functions/stripe-payments&lt;/code&gt; or &lt;code&gt;/.netlify/functions/handle-user-input&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In today's example, we want to take a user input, sent it to our function, and display the response for the user.&lt;/p&gt;

&lt;p&gt;For that we create a function at &lt;code&gt;serverless_functions/handle-user-input.js&lt;/code&gt;:&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="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryStringParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No input found&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we have learned earlier our function will be available at &lt;code&gt;.../.netlify/functions/handle-user-input&lt;/code&gt;, but how do we pass arguments to it? &lt;/p&gt;

&lt;p&gt;Of course, with URL parameters! &lt;/p&gt;

&lt;p&gt;Like so &lt;code&gt;.../.netlify/functions/handle-user-input?myparameter=somevalue&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Then we read the value by accessing queryStringParameters in the event object. In our case, the parameter we pass will be called "input".&lt;/p&gt;

&lt;h2&gt;
  
  
  Trigger a serverless function and receive a response
&lt;/h2&gt;

&lt;p&gt;Now that we have set up our serverless function, our users need to able to trigger it.&lt;/p&gt;

&lt;p&gt;It is as simple as fetching data from an API.&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="cm"&gt;/* ... imports etc. */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;allInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAllInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/.netlify/functions/user-input?input=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setAllInput&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please give me some input! 😥&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="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="nc"&gt;Layout&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;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&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="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;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&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;ul&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&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;allInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&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;item&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&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;ul&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;Layout&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things are happening here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We have an input field for users to enter any information and store that input using React's useState hook.&lt;/li&gt;
&lt;li&gt;We have a button to trigger the serverless function together with our input value using URL parameters. Then, when we receive a response, we add that string, to our array of responses called "allInput". Again, using React's useState hook for this.&lt;/li&gt;
&lt;li&gt;Lastly, we map through our array of responses and display any items in that list with an unordered list. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Demo&lt;/strong&gt; (&lt;a href="https://gatsby-with-netlify-functions.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) | &lt;strong&gt;Repo&lt;/strong&gt; (&lt;a href="https://github.com/LarsBehrenberg/gatsby-with-netlify-functions" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3sprzl6f1hd2bjkg89gz.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%2Fuploads%2Farticles%2F3sprzl6f1hd2bjkg89gz.png" alt="Gatsby with Netlify Serverless Functions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! You might feel like it's a little bit redundant to send the user's input through a serverless function, just to receive it again. But just think of all the different opportunities that this opens up for us! It's a powerful tool that allows you to turn your static site into a pretty much dynamic one! Let me know in the comments if you already have an idea of what you want to try and built with it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo&lt;/strong&gt; (&lt;a href="https://gatsby-with-netlify-functions.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) | &lt;strong&gt;Repo&lt;/strong&gt; (&lt;a href="https://github.com/LarsBehrenberg/gatsby-with-netlify-functions" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/" rel="noopener noreferrer"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The best way to load and use Google Fonts with React, Gatsby and NextJS</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Wed, 17 Feb 2021 10:19:14 +0000</pubDate>
      <link>https://dev.to/codetraveling/the-best-way-to-load-and-use-google-fonts-with-react-gatsby-and-nextjs-2m6i</link>
      <guid>https://dev.to/codetraveling/the-best-way-to-load-and-use-google-fonts-with-react-gatsby-and-nextjs-2m6i</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Google Fonts are amazing and widely popular on the Internet. Its API makes up 89.28% of the web fonts market share (see &lt;a href="https://www.datanyze.com/market-share/web-fonts--16"&gt;source&lt;/a&gt;). However, I often noticed that many websites struggle with fetching their fonts and end up render-blocking their website by up to 2 seconds!&lt;/p&gt;

&lt;p&gt;So, today I wanted to share the optimal way to load your Google Fonts without affecting your site performance. Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; How can I check whether fonts affect the performance of my website? &lt;/li&gt;
&lt;li&gt; FontSource (Self-host Google Fonts in neatly bundled NPM packages) &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How can I check whether my fonts affect my website's performance?
&lt;/h2&gt;

&lt;p&gt;I think many people might not even realize when loading fonts block the user from accessing their website. One of the most common resources to check this is Google's PageSpeed Lighthouse tool (&lt;a href="https://developers.google.com/speed/pagespeed/insights/"&gt;https://developers.google.com/speed/pagespeed/insights/&lt;/a&gt;). If you are having problems with your Google Fonts, it will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l9JBNrTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzajdlthuyu9447f7ika.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l9JBNrTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzajdlthuyu9447f7ika.png" alt="eliminate-render-blocking-resources.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here, the Google Font API needed a rocking 780ms to load in before elements on the website can be rendered. 780ms are eons for users. Just think of how much time we would steal over time from our users if every user has to wait this long.&lt;/p&gt;

&lt;h2&gt;
  
  
  FontSource (Self-host Google Fonts in neatly bundled NPM packages)
&lt;/h2&gt;

&lt;p&gt;And this is where &lt;a href="https://github.com/fontsource/fontsource"&gt;FontSource&lt;/a&gt; comes in. FontSource lets you self-host your fonts and gets rid of the need to include your fonts as &lt;code&gt;&amp;lt;link rel="stylesheet"&amp;gt;&lt;/code&gt;. No need to make a call to the Google Font API anymore, but instead have the font assets right in your project.&lt;/p&gt;

&lt;p&gt;FontSource essentially bundles open-source fonts like Google's in an NPM package that you can include in your project. All that's left to do is to import your font either in your &lt;code&gt;index.js&lt;/code&gt; or in your SCSS file. &lt;/p&gt;

&lt;p&gt;FontSource is very easy to configure and comes with great documentation. So, feel free to dive in there or follow the below for a simple implementation.&lt;/p&gt;

&lt;p&gt;Let's say we want to include the "Montserrat" font in our project. In 3 steps we are done.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Add the package to your project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;yarn&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="nd"&gt;@fontsource&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;montserrat&lt;/span&gt; &lt;span class="c1"&gt;// alternatively npm install @fontsource/montserra&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Import the font subsets necessary to your project in JavaScript or SCSS.
&lt;/h3&gt;

&lt;p&gt;To further improve performance, FontSource allows you to import subsets of the font to keep the payload small. &lt;/p&gt;

&lt;p&gt;In Javascript:&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="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fontsource/montserrat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Defaults to weight 400.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fontsource/montserrat/900-italic.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Italic variant.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or SCSS:&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~@fontsource/montserrat/index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Weight 400.&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~@fontsource/montserrat/300-italic.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Define the font in your CSS, CSS-in-JS etc.
&lt;/h3&gt;

&lt;p&gt;Now you are free to use the font in any place necessary. Whether you would like to reference it in CSS, CSS-in-JS, or SCSS.&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="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="s1"&gt;"Montserrat"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And gone are your issues with render-blocking fonts! I hope this helped. This tutorial has been quite simple and straightforward, but looking at the number of slow loading websites that I come across, with fonts loading in being the reason, I just felt like I had to make this post. Feel free to let me know in the comments if you feel the same!&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Top 10 resources to get better at CSS and become a better front-end developer 👨‍🎨👨‍💻</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 12 Feb 2021 10:26:48 +0000</pubDate>
      <link>https://dev.to/codetraveling/top-10-resources-to-get-better-at-css-and-become-a-better-front-end-developer-13n0</link>
      <guid>https://dev.to/codetraveling/top-10-resources-to-get-better-at-css-and-become-a-better-front-end-developer-13n0</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing CSS is hard.&lt;/strong&gt; Even though it often is made fun of and not seen as a programming language, writing consistent and pretty CSS is really hard. And in my journey as a self-taught web developer, I have often noticed that online classes and &lt;strong&gt;tutorials often skip the part to design your app with CSS&lt;/strong&gt; and don't go into detail about CSS best practices and more.&lt;/p&gt;

&lt;p&gt;And I feel that &lt;strong&gt;many other front-end developers struggle with this issue as well&lt;/strong&gt; if I look at the majority of portfolios out there. We learn how to build a restful API before we learn how to properly use the CSS transition or box-shadow attributes to style a simple button.&lt;/p&gt;

&lt;p&gt;That's why I have decided to share &lt;strong&gt;my top 10 resources on how to get better in CSS&lt;/strong&gt; with you, so your portfolio will impress your clients!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick note:&lt;/strong&gt; These resources are challenges and project-style meaning you learn through actively using CSS instead of going through tutorials or online classes! I much prefer this method as it teaches you how to look up things on your own instead of following a path that's laid out for you in class.&lt;/p&gt;

&lt;p&gt;With that said, &lt;strong&gt;let's get into it!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Frontend Mentor &lt;/li&gt;
&lt;li&gt; 100 Days of CSS (CSS Challenge) &lt;/li&gt;
&lt;li&gt; Front-End Challenges Club &lt;/li&gt;
&lt;li&gt; Daily UI &lt;/li&gt;
&lt;li&gt; CSS Battle &lt;/li&gt;
&lt;li&gt; Codier.io &lt;/li&gt;
&lt;li&gt; Build something you found on Dribbble &lt;/li&gt;
&lt;li&gt; 30 Days of CSS Girls &lt;/li&gt;
&lt;li&gt; Daily CSS Design &lt;/li&gt;
&lt;li&gt; Ace Front End &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://www.frontendmentor.io/" rel="noopener noreferrer"&gt;Frontend Mentor&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Frontend Mentor is hands down one of the best resources out there. Proving you real-world project ideas and free assets to build them, sharpening your CSS skills with this resource will also mean you end up having more assets in your portfolio!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.frontendmentor.io/" rel="noopener noreferrer"&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%2F7kel0zq8o0o5rc24ckh8.png" alt="Frontend Mentor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://100dayscss.com/" rel="noopener noreferrer"&gt;100 Days of CSS (CSS Challenge)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;100 Days of CSS is helpful as you can see what others have built and if you submit your own code, you will show up on the challenge site as well! This is also good if you are struggling, and just want to take some hints from other people's solutions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://100dayscss.com/" rel="noopener noreferrer"&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%2Fdh49cep0h3g1on50hdvj.png" alt="100dayscss.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://piccalil.li/category/front-end-challenges-club" rel="noopener noreferrer"&gt;Front-End Challenges Club&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The Front-End Challenges Club consists of 8 challenges by the &lt;a href="https://piccalil.li/" rel="noopener noreferrer"&gt;Piccalilli&lt;/a&gt; and their respective solutions. Some of the challenges come with assets if they are needed, so you can dive right in!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://piccalil.li/category/front-end-challenges-club" rel="noopener noreferrer"&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%2Fpv4m34gs1wjo6htpcccj.png" alt="front-end-challenge-club.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://www.dailyui.co/" rel="noopener noreferrer"&gt;Daily UI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;DailyUI is more a resource for designers than front-end developers, but nonetheless, I think it's well worth mentioning. I often get asked by my clients to come up with designs on my own or give recommendations, so I think any front-end developers should at least know some of the design concepts! You will notice the effect on your CSS skill for sure!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dailyui.co/" rel="noopener noreferrer"&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%2Fyf4xj4sqibtwzoeffeej.png" alt="dailyui.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://cssbattle.dev/" rel="noopener noreferrer"&gt;CSS Battle&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;CSS Battle has become very popular recently with some of the biggest web developer Youtubers battling each other in their videos. Challenges range from very beginner to very advanced and the game factor motivates, but writing quick solutions gets you more points instead of clean and consistent ones... Nonetheless, fun and learning in one!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cssbattle.dev/" rel="noopener noreferrer"&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%2F4w13s880zxbjqv7956xh.png" alt="cssbattle.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;a href="https://codier.io/" rel="noopener noreferrer"&gt;Codier.io&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Codier.io lets you create solutions to their challenge right in the browser and compare them with the community. However, most of the challenges are geared towards beginners, so this might be too easy for some of you!  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://codier.io/" rel="noopener noreferrer"&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%2Fayjqtwnezdgc5u2r6jz0.png" alt="codier.io.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;a href="https://dribbble.com/" rel="noopener noreferrer"&gt;Build something you found on Dribbble&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you haven't heard of Dribbble yet, it is one of the biggest platforms for designers to showcase their work on the web. From animations to product branding, print, and web and mobile design, you can find it all. It's a great resource to find beautiful web and mobile designs and recreate them in code for practice! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dribbble.com/" rel="noopener noreferrer"&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%2Fv62eqlrwmt72oxxk9ddl.png" alt="dribbble.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://css.codinggirls.sg/" rel="noopener noreferrer"&gt;30 Days of CSS Girls&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;30 Days of CSS Girls is a 30 Day Challenge that teaches you many of the basics of CSS and how they work. If you are a beginner, this might be where you want to start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css.codinggirls.sg/" rel="noopener noreferrer"&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%2Ff5a7en6azjlpitp2nfj1.png" alt="30-days-of-css-girls.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://dailycssdesign.com/" rel="noopener noreferrer"&gt;Daily CSS Design&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When I came across Daily CSS Design, I was stunned. It's a project by &lt;a href="https://www.behance.net/bear-bjorn" rel="noopener noreferrer"&gt;Bjørn Fjellstad&lt;/a&gt;, a designer and developer, who created a different design every day for one whole year. The designs in themselves are amazing, but the presentation on his website also speaks for itself. If you want to step up your CSS, you might want to get inspired here!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dailycssdesign.com/" rel="noopener noreferrer"&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%2Fcjd818h7ocnwnxzb73gv.png" alt="daily-css-design.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;a href="https://www.acefrontend.com/" rel="noopener noreferrer"&gt;Ace Front End&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;And lastly, Acer Front End. A beginner to intermediate level resource to let you become more confident (or not) in your skills as a developer. Finish the challenges right in the browser and become a "better" dev.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.acefrontend.com/" rel="noopener noreferrer"&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%2Fgt7t26m46a456bak1e5x.png" alt="acefrontend.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/" rel="noopener noreferrer"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Top 5 headless CMS and their pros and cons (Gatsby JS edition)</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 05 Feb 2021 08:25:42 +0000</pubDate>
      <link>https://dev.to/codetraveling/top-5-headless-cms-and-their-pros-and-cons-gatsby-js-edition-1f80</link>
      <guid>https://dev.to/codetraveling/top-5-headless-cms-and-their-pros-and-cons-gatsby-js-edition-1f80</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the reasons why Gatsby JS has been so popular over the years is its vast plugin library that makes it almost as easy as drag-and-drop to add new functionality to your app. &lt;/p&gt;

&lt;p&gt;Because of that, Gatsby has managed to make adding a headless CMS a straightforward and often very simple process that many other Static Site Generators (SSG) can only be astonished by.&lt;/p&gt;

&lt;p&gt;In this post, I wanna go my top 5 headless CMS that I have used with Gatsby JS in the past and their pros and cons. &lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Contentful&lt;/li&gt;
&lt;li&gt;Wordpress&lt;/li&gt;
&lt;li&gt;Prismic&lt;/li&gt;
&lt;li&gt;Netlify CMS&lt;/li&gt;
&lt;li&gt;Strapi&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.contentful.com/"&gt;Contentful&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We start with &lt;a href="https://www.contentful.com/"&gt;Contentful&lt;/a&gt;. Probably being one of the biggest players in the headless CMS market, Contentful gets also introduced first in the official Gatsby docs for "&lt;a href="https://www.gatsbyjs.com/docs/how-to/sourcing-data/sourcing-from-contentful/"&gt;sourcing data into Gatsby&lt;/a&gt;". &lt;/p&gt;

&lt;p&gt;It provides a user-friendly interface and organized, flexible data models with support for a variety of data types and content editors (e.g. WYSIWYGs, form fields, raw text areas).&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Available free tier that allows you to use it with 1 website using 2 locales, 48 content types and 2 user roles (admin &amp;amp; editor)&lt;/li&gt;
&lt;li&gt;Easy to set up&lt;/li&gt;
&lt;li&gt;Work with up to 5 users on a team on the free tier&lt;/li&gt;
&lt;li&gt;Great built-in versioning features with history and draft states&lt;/li&gt;
&lt;li&gt;Intuitive user interface&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Step from free to tier to paid is very expensive (US$489/month)&lt;/li&gt;
&lt;li&gt;Asset size max. 50MB&lt;/li&gt;
&lt;li&gt;Just 1 site on the free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://wordpress.org/"&gt;WordPress&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Just recently Hosting Tribunal put out &lt;a href="https://hostingtribunal.com/blog/wordpress-statistics/#gref"&gt;a new article on WordPress&lt;/a&gt;'s latest statistics stating this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WordPress powers 39.6% of the internet in 2021, a growth of nearly 5% from 35% in 2020, and a 4% rise from the year before.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HostingTribunal.com&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;But many people don't know that you could also use &lt;a href="https://wordpress.org/"&gt;WordPress&lt;/a&gt; as their headless CMS. Just the way you are used, but with Gatsby or other Static Site Generators (SSG) as the front-end.&lt;/p&gt;

&lt;p&gt;Made possible by the free and open-source &lt;a href="https://www.wpgraphql.com/"&gt;WPGraphQL plugin&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extensive documentation on the WordPress GraphQL plugin&lt;/li&gt;
&lt;li&gt;Many users are already familiar with the WordPress interface (usability+)&lt;/li&gt;
&lt;li&gt;Unlimited assets, users &amp;amp; content types&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More tedious/difficult to set up than most headless CMS&lt;/li&gt;
&lt;li&gt;WordPress needs to be hosted (not free)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://prismic.io/"&gt;Prismic&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://prismic.io/"&gt;Prismic&lt;/a&gt; is my headless CMS of choice for my &lt;a href="https://larsbehrenberg.com"&gt;personal website&lt;/a&gt; as the content management process for different languages works really well. &lt;/p&gt;

&lt;p&gt;The setup is a little tricky, but once you are through that the developing experience is very straightforward and easy. The extensive free tier is something I haven't been able to find anywhere else and for personal projects as a developer, I can recommend it. &lt;/p&gt;

&lt;p&gt;However, as soon as you would like to have people to access content without admin access, Prismic's price-point at 100$/month rules itself unfortunately out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Very extensive free tier with unlimited API Calls, Documents, Custom Types, Locales, Assets, Image Optimizations &amp;amp; 100 GB of Built-in CDN&lt;/li&gt;
&lt;li&gt;Very affordable plans for small teams (Starter Plan $7/month &amp;amp; Small Plan $15/month)&lt;/li&gt;
&lt;li&gt;Live Previews for content changes (with Gatsby currently not very stable, use NextJS instead)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Setup is not very straightforward with two different plugins gatsby-source-prismic-graphql &amp;amp; gatsby-source-prismic&lt;/li&gt;
&lt;li&gt;User roles are only available on plans for "organizations" starting at  $100/month, which makes Prismic unusable for small developers with individual clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.netlifycms.org/"&gt;Netlify CMS&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.netlifycms.org/"&gt;Netlify CMS&lt;/a&gt; has been together with Prismic one of my go-to-solutions when setting up a headless CMS. It's more configurable than other headless Markdown CMS like &lt;a href="https://forestry.io/"&gt;Forestry&lt;/a&gt; and has a community with the Netlify forum that's quick to help if you run into any problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to set up with several starter/templates available&lt;/li&gt;
&lt;li&gt;If properly set up, enjoy live previews within the CMS&lt;/li&gt;
&lt;li&gt;Open-source with no paid plans (free only)&lt;/li&gt;
&lt;li&gt;CMS lives right within your website and reads data from your Github repo markdown files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Although managed separately from Netlify the hosting service, Netlify CMS is difficult to set up on any other host than Netlify&lt;/li&gt;
&lt;li&gt;Not as versatile for users as other headless CMS&lt;/li&gt;
&lt;li&gt;i18n (Localization) is possible but not user or developer to set up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt; has been gaining a lot of traction recently and is becoming a popular solution as headless CMS. Providing an easy to configure Rest or GraphQL endpoint it can be virtually plugged in into any framework without a lot of trouble.&lt;/p&gt;

&lt;p&gt;Together with its plugin library and the ability to also manage file storage as well as email for you, makes Strapi definitely worth checking out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy installation and ability to use rest and graphql&lt;/li&gt;
&lt;li&gt;Extensive free tier (3 default roles etc.)&lt;/li&gt;
&lt;li&gt;Plugin library to extend Strapi&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;i18n (Localization) features are still not fully there yet&lt;/li&gt;
&lt;li&gt;Hosting generally costs (if not hosted on free Heroku bucket)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React and Gatsby JS got me started 🚀🔥 But what’s next?</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 29 Jan 2021 08:36:24 +0000</pubDate>
      <link>https://dev.to/codetraveling/react-and-gatsby-js-got-me-started-but-what-s-next-48dg</link>
      <guid>https://dev.to/codetraveling/react-and-gatsby-js-got-me-started-but-what-s-next-48dg</guid>
      <description>&lt;p&gt;*This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have been a freelance web developer for a while now, but in the beginning, I was always wondering whether &lt;strong&gt;WordPress development is going to be the only way&lt;/strong&gt; to create websites for my clients? I was looking for something to take advantage of my JavaScript knowledge and that's where I found &lt;strong&gt;Gatsby. It gave me the option to leave the WordPress space&lt;/strong&gt; and try out something else! But what's now? Is there something after Gatsby JS? That's what we will talk about today, &lt;strong&gt;so let's get right into it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Please note: This is the perspective of a web developer wanting to go freelance right from the beginning and not planning to get a corporate job.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; How I got started 

&lt;ul&gt;
&lt;li&gt; Getting into React
&lt;/li&gt;
&lt;li&gt; Getting into Gatsby JS &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt; The benefits of Gatsby JS &lt;/li&gt;
&lt;li&gt; Why you also might want to move on &lt;/li&gt;
&lt;li&gt; What's next? &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I got started
&lt;/h2&gt;

&lt;p&gt;Coming from a self-taught background, &lt;strong&gt;I got started, like so many others, with FreeCodeCamp&lt;/strong&gt;. It is in my opinion the single best resource to get your journey started and although many other resources have come out in the meantime, I think it is still the best.&lt;/p&gt;

&lt;p&gt;However, while I was doing FreeCodeCamp I had already started developing my first couple of WordPress websites. In the end, this combination proved good, as it taught me all the basics I needed to get started. But &lt;strong&gt;I soon grow discontent with WordPress and its long loading times&lt;/strong&gt; and lots of other things. &lt;/p&gt;

&lt;p&gt;I was wondering whether there is something I had missed in my FreeCodeCamp journey. Back in the day, the curriculum still consisted of only HTML, CSS, JS, and some backend certifications, but I wondered how do I now actually create a website for let's say a bakery around the corner?&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting into React
&lt;/h3&gt;

&lt;p&gt;I was reading lots about React on the internet, but FreeCodeCamp didn't have anything React-related in their curriculum at the time. So &lt;strong&gt;I started going onto Udemy&lt;/strong&gt; and searching for tutorials there.&lt;/p&gt;

&lt;p&gt;Eventually, I settled for &lt;a href="https://www.udemy.com/course/the-complete-web-developer-zero-to-mastery/"&gt;"The Complete Web Developer in 2021: Zero to Mastery" by Andrea Neagoie&lt;/a&gt;. Thought through and well structured 40 hours on-demand video course that filled in all the gaps that FreeCodeCamp had left me with.&lt;/p&gt;

&lt;p&gt;It helped me to get familiar with React file structure, JSX, the idea of component hierarchy and so much more. But again, i*&lt;em&gt;n the end, I had one more project on my portfolio, but was left wondering&lt;/em&gt;*, is this how you create a "normal" website if a friend reaches out to you and needs you to code up something simple? &lt;/p&gt;

&lt;h3&gt;
  
  
  Getting into Gatsby JS
&lt;/h3&gt;

&lt;p&gt;And that's where I found Gatsby JS. After searching for ways to reduce WordPress loading times and how to make "normal" websites with React, &lt;strong&gt;I came across this thing called "Jamstack"&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;And a day and 2 youtube videos later, I was following the Gatsby docs to set up my first Gatsby starter and browse through the numerous Gatsby files. &lt;/p&gt;

&lt;p&gt;Immediately, &lt;strong&gt;I was hooked.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first, it was a bit daunting to grasp was gatsby-node.js and gatsby-browser.js APIs meant, but with the huge community and the library of starters, &lt;strong&gt;it was just trial and error. The thing that every developer goes through&lt;/strong&gt; when learning new technologies, right? &lt;/p&gt;

&lt;h2&gt;
  
  
  The benefits of Gatsby JS
&lt;/h2&gt;

&lt;p&gt;Gatsby offered everything that I liked from WordPress development and more! With Gatsby's theme library I was able to &lt;strong&gt;peek at other people's projects and built on top of their themes&lt;/strong&gt; just like I would have in WordPress. But only this time, I could code in React. &lt;/p&gt;

&lt;p&gt;On top of it, &lt;strong&gt;hosting small Gatsby websites on Netlify with continuous deployment for basically free&lt;/strong&gt;, blew me away.&lt;/p&gt;

&lt;p&gt;Previously it had always been: "Host your WordPress website for only 5$/month". But now, instead, I was able to decide when to "publish" changes without immediately showing on my site like I had to with most of my WordPress clients.&lt;/p&gt;

&lt;p&gt;My time spent learning JavaScript and React now finally paid off too, and for the first time, I felt like FreeCodeCamp had been worth it.&lt;/p&gt;

&lt;p&gt;And what shocked me most, how easy it was to get &lt;strong&gt;high ratings on Google's Lighthouse Tool for performance as well as SEO&lt;/strong&gt;. Something that many clients cared about a lot.&lt;/p&gt;

&lt;p&gt;I now started to create websites with React and Gatsby instead of WordPress. I felt like I was more in control with less setup and could still give my clients access to their content through headless CMS easily. The best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you also might want to move on
&lt;/h2&gt;

&lt;p&gt;So why would I want to move on from Gatsby as it has made my developing experience so much better? Well, &lt;strong&gt;things on the Internet, and especially some of my views on web development have changed&lt;/strong&gt; since I got started with Gatsby. Gatsby is amazing, but it is definitely not the right answer to all static sites.&lt;/p&gt;

&lt;p&gt;The competition in the SSG (StaticSiteGenerator) field has become stronger each year, so much that things that used to be unique to Gatsby like effort-less image optimization and SEO have since been adopted by others and make it more difficult to argue why you should go with Gatsby.&lt;/p&gt;

&lt;p&gt;My clients' websites also have increased in size and often get updated which makes the &lt;strong&gt;build process with Gatsby quite tedious&lt;/strong&gt;. There are ways to improve build times, but what about the J*&lt;em&gt;avaScript and JSON bloat that gets shipped with every Gatsby site no matter what size&lt;/em&gt;*? Now some people will say that with the bloat come configured lots of Gatsby greatest advantages. But what if did not need or want them? I don't have the option to turn them off.&lt;/p&gt;

&lt;p&gt;Nowadays, I go for Gatsby if it's a site that needs to be set up quickly, is fairly small in size, and can perhaps be created by using one of the many starters that I have set up for myself in the past.&lt;/p&gt;

&lt;p&gt;The plugins that come with Gatsby are also generally great, especially for people getting started, but you might catch yourself later thinking: "Why am I googling whether there is a plugin, again? Shouldn't I maybe try and code this myself?.."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gatsby is just too convenient.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;From once being amazed by all the things that Gatsby provides you out of the box, I now often question myself if I really understood the concept of what I implemented or whether I just "copied and pasted".&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I have mentioned the growing competition that Gatsby (and React in general) is dealing with and some of the competitor's approaches are quite different and worth looking at. &lt;/p&gt;

&lt;p&gt;I think &lt;strong&gt;a developer should always strive to learn more&lt;/strong&gt; and not only deepen knowledge, but also accept that technologies sometimes change completely and as a developer, &lt;strong&gt;I might have to revise what I thought was good yesterday, but might not work anymore tomorrow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I know the React team and the Gatsby community are working relentlessly to improve every day, but I increasingly have a tingle in my fingers that tells me to step out of my comfort zone and try out something new.&lt;/p&gt;

&lt;p&gt;One topic that I have come across, again and again, is &lt;strong&gt;Svelte with Snowpack&lt;/strong&gt;. Getting rid of the bloat from React and offering an even better developer experience, seems very promising.&lt;/p&gt;

&lt;p&gt;It's currently used by sites like the New York Times, Spotify, Ikea, and Chess.com. These are some really big players that seemed confident enough in Svelte to take the plunge! &lt;strong&gt;So this is  something I definitely want to try out in 2021!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The other probably &lt;strong&gt;more popular choice is VueJS&lt;/strong&gt;. Becoming very hyped over the last few years, I think we all should at least dabble in the "Hello World" starter and see for ourselves if the hype is justified. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And this is one of the many reasons I love web development.&lt;/strong&gt; The community strives to challenge each other and constantly introduces new and potentially better concepts. Always on the hunt for a better approach for developers and users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What will you learn in 2021?&lt;/strong&gt; Will you also leave your comfort zone and see what else is out there? Let me know in the comments!&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>gatsby</category>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Use Javascript's Fetch API with async/await to fetch your Instagram feed in React</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 22 Jan 2021 09:44:33 +0000</pubDate>
      <link>https://dev.to/codetraveling/use-javascript-s-fetch-api-with-async-await-to-fetch-your-instagram-feed-in-react-67n</link>
      <guid>https://dev.to/codetraveling/use-javascript-s-fetch-api-with-async-await-to-fetch-your-instagram-feed-in-react-67n</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Especially for blogs these days, &lt;strong&gt;Instagram feed implementations&lt;/strong&gt; have become more and more popular. In Gatsby JS case, I have often used this handy plugin called &lt;a href="https://github.com/oorestisime/gatsby-source-instagram"&gt;gatsby-source-instagram&lt;/a&gt;, but as new images are only loaded during build time and not on page load, I have recently gone over to use &lt;strong&gt;a more general approach using JavaScripts Fetch API with Async/Await&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get into it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;**Quick note:&lt;/em&gt;* Here is the &lt;a href="https://github.com/LarsBehrenberg/gatsby-instagram-feed"&gt;repo&lt;/a&gt; and the &lt;a href="https://gatsby-instagram-feed.netlify.app/"&gt;demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Set up your React Component &lt;/li&gt;
&lt;li&gt; Fetch your Instagram posts with &lt;em&gt;Async/Await&lt;/em&gt; &lt;/li&gt;
&lt;li&gt; Display your posts and show likes on hover &lt;/li&gt;
&lt;li&gt; Implement a loading state while fetching posts
&lt;/li&gt;
&lt;li&gt; The final result &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up your React Component
&lt;/h2&gt;

&lt;p&gt;Now before we get right into, this is what our bare React Component will look like:&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="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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Your Instragam ID can be retrieved here. Just make sure to replace your instagram name at the end&lt;/span&gt;
  &lt;span class="c1"&gt;// https://www.instagram.com/web/search/topsearch/?context=blended&amp;amp;query=INSTAGRAM_USERNAME&lt;/span&gt;

  &lt;span class="c1"&gt;// Your specifications needed for the fetch call later&lt;/span&gt;
  &lt;span class="nx"&gt;INSTAGRAM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;787132&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;THUMBNAIL_WIDTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;640&lt;/span&gt;
  &lt;span class="nx"&gt;PHOTO_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// later fetch our posts here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* map through our posts here */&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;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Two things are important to note here!&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Our state is storing an empty array which we will later use to store our images once loaded and secondly, a loading boolean which we will use to show a loading animation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The variables below are specifications for our fetch call later. By switching out the username at the end, you can use this URL:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://www.instagram.com/web/search/topsearch/context=blended&amp;amp;query=INSTAGRAM_USERNAME"&gt;https://www.instagram.com/web/search/topsearch/context=blended&amp;amp;query=INSTAGRAM_USERNAME&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;to make a GET request to the Instagram API and get your specific ID for your account. Once that's done, you choose your thumbnail width needed and the number of images you would like to load.&lt;/p&gt;

&lt;p&gt;Thumbnails are available with these sizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;150&lt;/li&gt;
&lt;li&gt;240&lt;/li&gt;
&lt;li&gt;320&lt;/li&gt;
&lt;li&gt;480&lt;/li&gt;
&lt;li&gt;640&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fetch your Instagram posts with &lt;em&gt;Async/Await&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Async/Await allows us to asynchronously load our page while we are fetching our posts in our componentDidMount function. This looks like so:&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="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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Your specifications&lt;/span&gt;
  &lt;span class="nx"&gt;INSTAGRAM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;787132&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;THUMBNAIL_WIDTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;640&lt;/span&gt;
  &lt;span class="nx"&gt;PHOTO_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Hack from https://stackoverflow.com/a/47243409/2217533&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`https://www.instagram.com/graphql/query?query_id=17888483320059182&amp;amp;variables={"id":"&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INSTAGRAM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;","first":&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PHOTO_COUNT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,"after":null}`&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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_owner_to_timeline_media&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_to_comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_preview_like&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;caption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_to_caption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail_resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config_width&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;THUMBNAIL_WIDTH&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;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;config_width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;config_height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.instagram.com/p/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortcode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;likes&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* map through our posts here */&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;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use our try/catch block for our API GET call, we have to &lt;strong&gt;make our componentDidMount function asynchronous&lt;/strong&gt;. Then we can use the &lt;strong&gt;fetch API with the await keyword to call the API&lt;/strong&gt; and get the data to our specifications. All that is left, is to &lt;strong&gt;de-structure the variables&lt;/strong&gt; that we need into the photos array &lt;strong&gt;in our state&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display your posts and show likes on hover
&lt;/h2&gt;

&lt;p&gt;Now that we have received and stored our posts, we can go ahead and map through them.&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="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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// ... previous code here  &lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* map through our posts here */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;caption&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
                &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item"&lt;/span&gt;
                &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"noopener noreferrer"&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&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="nt"&gt;img&lt;/span&gt;
                  &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-image"&lt;/span&gt;
                  &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&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="nt"&gt;a&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="si"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we are saying that, if photos is not empty or in that sense equals true, run the items in the array and show me the images. &lt;/p&gt;

&lt;p&gt;But to get a more Instagram-like experience, we also want to show the number of likes and comments on hover. Now for this, we need to add some CSS as well, so please note the import at the top. I won't go into details about the CSS here, but you can find the code on my Github here.&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="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="c1"&gt;// Styles&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./instagram.css&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="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// ... previous code here&lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* map through our posts here */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;caption&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
                &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item"&lt;/span&gt;
                &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"noopener noreferrer"&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&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="nt"&gt;img&lt;/span&gt;
                  &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-image"&lt;/span&gt;
                  &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*  */&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-info"&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;ul&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;li&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-likes"&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;span&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt; &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"heart"&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;svg&lt;/span&gt;
                          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
                          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.45&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 4.435C10.011-.964 0-.162 0 8.003 0 12.071 3.06 17.484 12 23c8.94-5.516 12-10.929 12-14.997C24-.115 14-.996 12 4.435z"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;path&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;svg&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&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;li&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;li&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-comments"&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;span&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt; &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"speech-balloon"&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;svg&lt;/span&gt;
                          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
                          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.45&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M24 9.874C24 4.42 18.627 0 12 0S0 4.42 0 9.874c0 4.512 3.678 8.317 8.701 9.496L12 24l3.299-4.63C20.322 18.19 24 14.385 24 9.874z"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;path&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;svg&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&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;li&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;ul&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="si"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implement a loading state while fetching posts
&lt;/h2&gt;

&lt;p&gt;At last, we want to show something while we are fetching the posts so that the user knows something is going on in the background. That's why we have our loading boolean in our state. &lt;/p&gt;

&lt;p&gt;You might have noticed already, but after we fetched our posts and stored them in our state, we are also setting our loading boolean to false. With this in mind, all that is left is to have an if-else statement in our JSX to toggle between loading and showing pictures.&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;// ... imports here&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ... your specifications here&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// ... fetching posts here and then set loading state to false&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&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="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading ...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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="p"&gt;(&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;caption&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="c1"&gt;// ... previous code here&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="si"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The final result
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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="c1"&gt;// Styles&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./instagram.css&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="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Instagram&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Your specifications&lt;/span&gt;
  &lt;span class="nx"&gt;INSTAGRAM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;787132&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;THUMBNAIL_WIDTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;640&lt;/span&gt;
  &lt;span class="nx"&gt;PHOTO_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Hack from https://stackoverflow.com/a/47243409/2217533&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`https://www.instagram.com/graphql/query?query_id=17888483320059182&amp;amp;variables={"id":"&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INSTAGRAM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;","first":&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PHOTO_COUNT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,"after":null}`&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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_owner_to_timeline_media&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_to_comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_preview_like&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;caption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edge_media_to_caption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail_resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config_width&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;THUMBNAIL_WIDTH&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;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;config_width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;config_height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.instagram.com/p/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortcode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;likes&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&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="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading ...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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="p"&gt;(&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;caption&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
                &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item"&lt;/span&gt;
                &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"noopener noreferrer"&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&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="nt"&gt;img&lt;/span&gt;
                  &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-image"&lt;/span&gt;
                  &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*  */&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-info"&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;ul&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;li&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-likes"&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;span&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt; &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"heart"&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;svg&lt;/span&gt;
                          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
                          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.45&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 4.435C10.011-.964 0-.162 0 8.003 0 12.071 3.06 17.484 12 23c8.94-5.516 12-10.929 12-14.997C24-.115 14-.996 12 4.435z"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;path&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;svg&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&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;li&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;li&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post-item-comments"&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;span&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt; &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"speech-balloon"&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;svg&lt;/span&gt;
                          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1em"&lt;/span&gt;
                          &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
                          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.45&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M24 9.874C24 4.42 18.627 0 12 0S0 4.42 0 9.874c0 4.512 3.678 8.317 8.701 9.496L12 24l3.299-4.63C20.322 18.19 24 14.385 24 9.874z"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;path&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;svg&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&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;li&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;ul&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="p"&gt;)&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;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the CSS:&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;.post-wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;12rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-image&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.4rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&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="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item-likes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.post-item-info&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.post-item&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="nc"&gt;.post-item-info&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;place-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item-info&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&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;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.4rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item-info&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-item-info&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>codenewbie</category>
      <category>gatsby</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Top 50 Gatsby plugins you're going to love 🔥👨‍💻</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Fri, 15 Jan 2021 07:53:12 +0000</pubDate>
      <link>https://dev.to/codetraveling/top-50-gatsby-plugins-you-re-going-to-love-71a</link>
      <guid>https://dev.to/codetraveling/top-50-gatsby-plugins-you-re-going-to-love-71a</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the many things that might get people to use Gatsby JS is &lt;strong&gt;the vast Gatsby Plugin Library&lt;/strong&gt; that comes with it. &lt;strong&gt;Thousands of different plugins&lt;/strong&gt;, built by the Gatsby team, the community, or sole developers with almost &lt;strong&gt;seamless drop-in support&lt;/strong&gt; make the developing experience with Gatsby very smooth. In this post, we will go through &lt;strong&gt;my top 50 plugins&lt;/strong&gt; with all kinds of different purposes and categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Please note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;there are lots of basic plugins I have left out in this list, although there are amazing! Let me know in the comments what plugins you guys use!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Styling &lt;/li&gt;
&lt;li&gt; Markdown &lt;/li&gt;
&lt;li&gt; CMS &lt;/li&gt;
&lt;li&gt; Socials &lt;/li&gt;
&lt;li&gt; Analytics / SEO &lt;/li&gt;
&lt;li&gt; Hosting &lt;/li&gt;
&lt;li&gt; Other &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Styling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-styled-components/?=styled"&gt;gatsby-plugin-styled-components&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Styled Components, maybe the most popular of the "CSS-in-JS" solutions, makes probably for a good start to this list of top 50 plugins. Find out more about how to implement it in your existing repo in this &lt;a href="https://www.digitalocean.com/community/tutorials/gatsbyjs-using-styled-components-in-gatsbyjs"&gt;DigitalOcean article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-emotion/?=emo"&gt;gatsby-plugin-emotion&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Emotion is the counter-part to Styled Components and arguably the second most popular "CSS-in-JS" solution. Let me know in the comments which you like best!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-typography/?=typo"&gt;gatsby-plugin-typography&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;TypographyJS is a tool I often use for my sites and this Gatsby JS plugin makes sure to include it with minimal configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-sass/"&gt;gatsby-plugin-sass&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;For people who prefer Sass/SCSS over "CSS-in-JS" or standard CSS we have gatsby-plugin-sass providing drop-in support for Sass/SCSS stylesheets&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-postcss/"&gt;gatsby-plugin-postcss&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;And if you want to use PostCSS "the tool for transforming CSS with JavaScript", we've got you covered as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-purgecss/"&gt;gatsby-plugin-purgecss&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Remove unused CSS from CSS/Sass/Less/stylus files and modules in your Gatsby project using purgecss. 🎉 Supports tailwind, bootstrap, bulma, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-material-ui/"&gt;gatsby-plugin-material-ui&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The plugin to include Material-UI v4 in your project. However you might want to consider using "&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-theme-material-ui/"&gt;gatsby-theme-material-ui&lt;/a&gt;" which already uses the plugin under the hood, adds web fonts, meta-viewport, CSS baseline, and MaterialUI theme support and has MaterialUI styled Gatsby link components.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-chakra-ui"&gt;gatsby-plugin-chakra-ui&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Drop-In support for &lt;a href="https://chakra-ui.com/"&gt;Chakra-UI&lt;/a&gt;! "Chakra UI is a simple, modular, and accessible component library that gives you the building blocks you need to build your React applications." - chakra-ui.com. &lt;/p&gt;

&lt;h3&gt;
  
  
  9. &lt;a href="https://www.npmjs.com/package/gatsby-plugin-antd"&gt;gatsby-plugin-antd&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Drop-In support for &lt;a href="https://ant.design/"&gt;AntDesign&lt;/a&gt;! 🌈 Enterprise-class UI designed for web applications. 📦 A set of high-quality React components out of the box. 🛡 Written in TypeScript with predictable static types. ⚙️ A whole package of design resources and development tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  10. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx/"&gt;gatsby-plugin-mdx&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;gatsby-plugin-mdx is the official integration for using MDX with Gatsby. The default configuration will allow you to automatically create pages with .mdx files in src/pages and will process any Gatsby nodes with Markdown media types into MDX content! 🔥&lt;/p&gt;

&lt;h3&gt;
  
  
  11. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs/"&gt;gatsby-remark-prismjs&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;PrismJS is a syntax highlighter for your code snippets on your Gatsby Blog! Lightweight and extensible! Checkout different themes at &lt;a href="https://prismjs.com/"&gt;PrismJS&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  12. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-remark-embed-video/?=video"&gt;gatsby-remark-embed-video&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now, what if you want to embed a Youtube video in your Markdown? You can write the code to detect it yourself or you can use gatsby-remark-embed-video!&lt;/p&gt;

&lt;h3&gt;
  
  
  13. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-remark-reading-time/?=reading%20time"&gt;gatsby-remark-reading-time&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Becoming more popular each day, you can now add a reading-time tag to your blog posts like you see on Medium on really anywhere these days!&lt;/p&gt;

&lt;h3&gt;
  
  
  14. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-remark-autolink-headers/"&gt;gatsby-remark-autolink-headers&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This plugin automatically turns your Markdown headers into GitHub-style hover-links! Note: this is a sub-plugin to the &lt;em&gt;gatsby-transformer-remark&lt;/em&gt; plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. &lt;a href="https://www.gatsbyjs.com/plugins/@weknow/gatsby-remark-twitter/?=twitter%20remark"&gt;gatsby-remark-twitter&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of Youtube Videos, with this plugin, you can embed any Tweet or Moment right in your Markdown files!&lt;/p&gt;

&lt;h3&gt;
  
  
  16. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-remark-smartypants/"&gt;gatsby-remark-smartypants&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Next up is another sub-plugin of &lt;em&gt;gatsby-transformer-remark&lt;/em&gt;, this time we can automatically replace “dumb” punctuation marks with “smart” punctuation marks. This uses the retext-smartypants plugin under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  CMS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  17. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-netlify-cms/"&gt;gatsby-plugin-netlify-cms&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now if you didn't want to go with managing markdown files on your own, the next best and easy option for you is NetlifyCMS. A CMS deployed with your Gatsby Netlify Site makes changing and previewing your markdown files easy!&lt;/p&gt;

&lt;h3&gt;
  
  
  18. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-prismic/"&gt;gatsby-source-prismic&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Prismic CMS is a little bit more difficult to configure, but once you have the setup, it's a really good option for a multilingual website like &lt;a href="https://larsbehrenberg.com"&gt;my own&lt;/a&gt;! Create and source content in different languages to programmatically create your pages in Gatsby for you!&lt;/p&gt;

&lt;h3&gt;
  
  
  19. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-contentful/"&gt;gatsby-source-contentful&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is probably one of the most popular options for headless CMS. Easy to set up with a simple web interface, Contentful has become one of the biggest in the market.&lt;/p&gt;

&lt;h3&gt;
  
  
  20. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-datocms/?=gatsby-source-datocms"&gt;gatsby-source-datocms&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Another headless option is DatoCMS. It excels at managing pages with complex layouts or big teams with multi-roles, for bigger sized companies this is definitely worth considering!&lt;/p&gt;

&lt;h3&gt;
  
  
  21. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-sanity/?=gatsby-source-sanity"&gt;gatsby-source-sanity&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Sanity allows for real-time content preview in development and minimal configuration to get started. Check out the guide to get started &lt;a href="https://www.sanity.io/blog/get-started-with-gatsby-and-structured-content"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  22. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-airtable/"&gt;gatsby-source-airtable&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Source your data into your Gatsby application from your Airtable base tables. "Airtable evolves with you and your team, so you can build a solution with increasing sophistication and capability." - airtable.com&lt;/p&gt;

&lt;h3&gt;
  
  
  23. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-strapi/"&gt;gatsby-source-strapi&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;"Building self-hosted, customizable, and performant content API has never been easier." - Strapi.io. This our first self-hosted option!&lt;/p&gt;

&lt;h3&gt;
  
  
  24. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-wordpress/?=wordpress"&gt;gatsby-source-wordpress&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This plugin will soon be deprecated for the next version v4, but still worth mentioning! Over 35% of the web is powered by WordPress and some might want to think about just deploying the frontend with Gatsby. With this plugin, you can! Source your WordPress content on build time and get Gatsby's blazing fast front-end on top! ⚡️&lt;/p&gt;

&lt;h2&gt;
  
  
  Socials
&lt;/h2&gt;

&lt;h3&gt;
  
  
  25. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-social9-socialshare/"&gt;gatsby-plugin-social9-socialshare&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Do you want sharing buttons for your blog posts? This plugin is for you! Social9 social sharing provides you beautiful buttons, sharing capabilities, and analytics. (20+ buttons- Whatsapp, Facebook, Twitter, LinkedIn, Reddit, and many more…)&lt;/p&gt;

&lt;h3&gt;
  
  
  26. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-social-cards/#:~:text=Automatically%20parses%20your%20posts%20and,on%20meta%2Dtags%20for%20social."&gt;gatsby-plugin-my-social-cards&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Parse your posts and generate socials cards for Twitter, Facebook, Slack, and more! You can also configure lots on your own like custom backgrounds, custom author images, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  27. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-instagram/"&gt;gatsby-source-instagram&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Sourcing data from Instagram hasn't been easier. Scrape posts from an account or a hashtag. Or scrape user profile information if that's what you are after!&lt;/p&gt;

&lt;h3&gt;
  
  
  28. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-twitter/"&gt;gatsby-source-twitter&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If Twitter is what you are after instead of Instagram, this plugin has got you covered. The plugin supports 8 different API endpoints from Twitter's official API and you can pull it right into your Gatsby site.&lt;/p&gt;

&lt;h3&gt;
  
  
  29. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-mailchimp/"&gt;gatsby-plugin-mailchimp&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Some people might be trying to create a newsletter following and with this Mailchimp plugin, it just becomes easier! There are lots of other options for providers, but Mailchimp is one of the most popular.&lt;/p&gt;

&lt;h3&gt;
  
  
  30. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-feed"&gt;gatsby-plugin-feed&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Do you want your blog to be available as an RSS feed? This plugin gives you all the configuration options you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analytics / SEO
&lt;/h2&gt;

&lt;h3&gt;
  
  
  31. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-google-analytics/"&gt;gatsby-plugin-google-analytics&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Understanding your users and how they behave is key to creating a following. The most popular option is Google Analytics. This plugin offers drop-in support for the "not yet" deprecated Google Analytics.&lt;/p&gt;

&lt;h3&gt;
  
  
  32. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-google-gtag/?=gtag"&gt;gatsby-plugin-google-gtag&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Google gtag is the newest version of Google Analytics, also called Google Analytics v4 supporting the GA4 property. If you signed up recently, this is most likely what you got. Make sure to use this plugin for drop-in support then! &lt;/p&gt;

&lt;h3&gt;
  
  
  33. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-google-tagmanager/"&gt;gatsby-plugin-google-tagmanager&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you want Google Tagmanager on your Gatsby site. This plugin is for you. Add your Google ID and off you go!&lt;/p&gt;

&lt;h3&gt;
  
  
  34. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-sentry/"&gt;gatsby-plugin-sentry&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;"Sentry's application monitoring platform helps every developer diagnose, fix, and optimize the performance of their code. Over 1M developers and 60K organizations already ship better software faster with Sentry. Won’t you join them? " - &lt;a href="http://sentry.io"&gt;Sentry.io&lt;/a&gt; Why not with this Gatsby plugin?&lt;/p&gt;

&lt;h3&gt;
  
  
  35. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-sitemap/"&gt;gatsby-plugin-sitemap&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create your sitemap with ease! But why do you even need one? &lt;a href="https://www.imarc.com/blog/do-sites-really-need-a-sitemap-for-seo"&gt;This article&lt;/a&gt; goes through the basics and most importantly explains its use cases!&lt;/p&gt;

&lt;h3&gt;
  
  
  36. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-robots-txt/"&gt;gatsby-plugin-robots-txt&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Next up is the robots.txt. One line in your gatsby-config.js and you are good to go. If want to learn more about it, check out &lt;a href="https://moz.com/learn/seo/robotstxt"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  37. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-guess-js/"&gt;gatsby-plugin-guess-js&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Guess.js is a library for enabling data-driven user-experiences on the web. This plugin will predict which page a user is most likely to visit from a given page by automatically downloading your Google Analytics data and use this data to create a model!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  38. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-s3/"&gt;gatsby-plugin-s3&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are lots of different options for hosting, but among them, the two most common I use are Amazon S3 Buckets and Netlify. This plugin focuses on the S3 buckets and makes deployment easy!&lt;/p&gt;

&lt;h3&gt;
  
  
  39. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-netlify/"&gt;gatsby-plugin-netlify&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now Netlify is probably one the most popular options to deploy your Gatsby site and this plugin will automatically generate a _headers and a _redirects at the root of your public folder to configure HTTP headers and redirects on Netlify.&lt;/p&gt;

&lt;h3&gt;
  
  
  40. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-netlify-cache/"&gt;gatsby-plugin-netlify-cache&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;One thing Gatsby has already struggled with is Build speed on subsequent builds. This plugin might be for you in that case. Caching your previous builds locally or in the Netlify cache directory, this plugin can speed up your build times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other
&lt;/h2&gt;

&lt;h3&gt;
  
  
  41. &lt;a href="https://github.com/angeloocana/gatsby-plugin-i18n"&gt;gatsby-plugin-i18n&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you are trying to build a multi-language website with Gatsby? Then, this plugin might be for you. Automatically built different languages for different file paths like &lt;strong&gt;src/pages/about.en.js ⇒ /en/about&lt;/strong&gt; or &lt;strong&gt;src/pages/about.jp.js ⇒ /jp/about&lt;/strong&gt;! &lt;/p&gt;

&lt;h3&gt;
  
  
  42. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-scroll-reveal/"&gt;gatsby-plugin-scroll-reveal&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I &lt;a href="https://blog.larsbehrenberg.com/the-easiest-way-to-do-scroll-animations-in-gatsbyjs"&gt;talked about this plugin&lt;/a&gt; in one of my recent posts on how to get scroll animations done easily in Gatsby! Based on the &lt;a href="https://mciastek.github.io/sal/"&gt;Sal (Scroll Animation Library)&lt;/a&gt; this plugin is fire! 🔥&lt;/p&gt;

&lt;h3&gt;
  
  
  43. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-nprogress/"&gt;gatsby-plugin-page-progress&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Or maybe you fancy a progress indicator for page scrolling at the top of your page? Then this plugin is for you. Based on NProgress.js, it is very handy and easy to set up. &lt;/p&gt;

&lt;h3&gt;
  
  
  44. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-prefetch-google-fonts/"&gt;gatsby-plugin-prefetch-google-fonts&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Is loading Google Fonts in slowing down your site? Maybe you should prefetch them? With this plugin, you can prefetch your fonts and increase performance as opposed to loading web fonts from Google’s external stylesheet.&lt;/p&gt;

&lt;h3&gt;
  
  
  45. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-transformer-json/"&gt;gatsby-transformer-json&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Some people working with JSON files as their database, but at last want to access them as JavaScript objects, this plugin is for them. Parse raw JSON strings into JavaScript objects e.g. from JSON files. Also supports arrays of objects and single objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  46. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-local-search/"&gt;gatsby-plugin-local-search&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In case you want to search your GraphQL layer using a search engine like &lt;a href="https://github.com/nextapps-de/flexsearch"&gt;FlexSearch&lt;/a&gt;, you might want to have a look at this plugin!&lt;/p&gt;

&lt;h3&gt;
  
  
  47. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-breadcrumb/"&gt;gatsby-plugin-breadcrumb&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Do you need the user to know, where there are in the page hierarchy? Do you want them to find their way back? Simply use &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-breadcrumb/"&gt;Breadcrumbs&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  48. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-chatwoot/"&gt;gatsby-plugin-chatwoot&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Chatwoot is a live chat software for websites running on open-source! With a very generous free-tier, this is one of my favorites on this list!&lt;/p&gt;

&lt;h3&gt;
  
  
  49. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-preact/"&gt;gatsby-plugin-preact&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;One of Gatsby's downsides especially recently has been the Javascript file size it needs to ship with the application. Preact is working to solve that. While Preact doesn’t provide full support for the React ecosystem, it is an intriguing option for Gatsby sites as it saves ~30kb of JavaScript vs. using React!&lt;/p&gt;

&lt;h3&gt;
  
  
  50. &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-page-creator/"&gt;gatsby-plugin-page-creator&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is an official Gatsby plugin, and by default works only with the /pages directory, but what if you want to use another directory for automatically generating pages? Simply add this plugin in your gatsby-config.js, define your custom directory, and let's goo!!&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far!&lt;/p&gt;

&lt;p&gt;And I hope you found a few plugins in this list that you might not have known about yet and are going to try out in the future! There are thousands of different plugins and especially the CMS plugins make Gatsby so powerful to me. Being able to easily access the contents on build time from your CMS without having to go to much length is just so nice.&lt;/p&gt;

&lt;p&gt;Let me know in the comments what plugins you like the best!&lt;/p&gt;

&lt;p&gt;And feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The easiest way to do scroll animations in GatsbyJS</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Mon, 04 Jan 2021 13:51:07 +0000</pubDate>
      <link>https://dev.to/codetraveling/the-easiest-way-to-do-scroll-animations-in-gatsbyjs-45pg</link>
      <guid>https://dev.to/codetraveling/the-easiest-way-to-do-scroll-animations-in-gatsbyjs-45pg</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One thing that many of my clients are asking for these days is to include slide-in, pop up, or some other kind of animation on their website.&lt;/p&gt;

&lt;p&gt;And you can go ahead and write the CSS yourself or use a more React-oriented solution like &lt;strong&gt;react-intersection-observer&lt;/strong&gt;. But in this example, I would like to show you a shortcut when the budget is tight.&lt;/p&gt;

&lt;p&gt;A gatsby community plugin called &lt;strong&gt;gatsby-plugin-scroll-reveal&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Under the hood, it uses the &lt;a href="https://mciastek.github.io/sal/"&gt;Sal (Scroll Animation Library)&lt;/a&gt;, which focuses on performance and is less than 2.8kb, written in vanilla Javascript. &lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; IE11 is supported&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Install and implement the plugin in your gatsby-config.js &lt;/li&gt;
&lt;li&gt; How to enable animations in your components &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install and implement the plugin in your gatsby-config.js
&lt;/h2&gt;

&lt;p&gt;The setup is quite simple, as with most Gatsby plugins.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install &lt;strong&gt;gatsby-plugin-scroll-reveal&lt;/strong&gt; with yarn or npm (depending on your preference):&lt;br&gt;
&lt;code&gt;yarn add gatsby-plugin-scroll-reveal&lt;/code&gt;&lt;br&gt;
or&lt;br&gt;
&lt;code&gt;npm install --save gatsby-plugin-scroll-reveal&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And add the plugin in your &lt;strong&gt;gatsby-config.js&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in gatsby-config.js&lt;/span&gt;
&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ... other plugins&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-scroll-reveal`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Percentage of an element's area that needs to be visible to launch animation&lt;/span&gt;
        &lt;span class="na"&gt;once&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Defines if animation needs to be launched once&lt;/span&gt;
        &lt;span class="na"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Flag for disabling animations&lt;/span&gt;

        &lt;span class="c1"&gt;// Advanced Options&lt;/span&gt;
        &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-sal]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Selector of the elements to be animated&lt;/span&gt;
        &lt;span class="na"&gt;animateClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sal-animate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Class name which triggers animation&lt;/span&gt;
        &lt;span class="na"&gt;disabledClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sal-disabled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Class name which defines the disabled state&lt;/span&gt;
        &lt;span class="na"&gt;rootMargin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0% 50%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Corresponds to root's bounding box margin&lt;/span&gt;
        &lt;span class="na"&gt;enterEventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sal:in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Enter event name&lt;/span&gt;
        &lt;span class="na"&gt;exitEventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sal:out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Exit event name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you are using &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-transition-link/?__hstc=247646936.5a70aa85a50443989ce365cee06359b1.1606179439689.1608090555014.1608883300963.15&amp;amp;__hssc=247646936.2.1608883300963&amp;amp;__hsfp=2249640406"&gt;Gatsby Plugin Transition Link&lt;/a&gt; as well as this plugin, make sure to add this plugin before &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-transition-link/?__hstc=247646936.5a70aa85a50443989ce365cee06359b1.1606179439689.1608090555014.1608883300963.15&amp;amp;__hssc=247646936.2.1608883300963&amp;amp;__hsfp=2249640406"&gt;Gatsby Plugin Transition Link&lt;/a&gt; in the config.&lt;/p&gt;

&lt;p&gt;Note, that what you see here are the default options for the plugin.&lt;/p&gt;

&lt;p&gt;If you don't want to change any of them, you can also include the plugin without &lt;code&gt;options&lt;/code&gt; to keep your &lt;strong&gt;gatsby-config.js&lt;/strong&gt; cleaner:&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="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ... other plugins&lt;/span&gt;
  &lt;span class="s2"&gt;`gatsby-plugin-scroll-reveal`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to enable animations in your components
&lt;/h2&gt;

&lt;p&gt;Now, we only need to let &lt;code&gt;gatsby-plugin-scroll-reveal&lt;/code&gt; know, which components we would like to animate.&lt;/p&gt;

&lt;p&gt;We do this by giving the wrapper div of our component some data attributes.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;YourFunction&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;YourComponent&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;sal&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"slide-up"&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;sal&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2000"&lt;/span&gt; &lt;span class="c1"&gt;// changes duration of the animation (from 200 to 2000 ms)&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;sal&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="c1"&gt;// adds delay to the animation (from 5 to 1000 ms)&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;sal&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ease"&lt;/span&gt; &lt;span class="c1"&gt;// sets easing for the animation (see easings.net for reference)&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;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;YourComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our &lt;strong&gt;main data-sal attribute&lt;/strong&gt;, we have several different options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fade&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slide-up&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slide-down&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slide-left&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slide-right&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zoom-in&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zoom-out&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flip-up&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flip-down&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flip-left&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flip-right&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for &lt;strong&gt;data-sal-easing&lt;/strong&gt;, ****we can choose from several different options as well. You can find a list here at &lt;a href="https://easings.net/"&gt;easings.net&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that concludes this tutorial for today! &lt;strong&gt;SAL&lt;/strong&gt; does all of the heavy lifting for us and with less than &lt;strong&gt;2.8 kb bundle size&lt;/strong&gt;, there is not much that we can complain about if we are in need of a &lt;strong&gt;quick and easy to implement solution&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>webdev</category>
      <category>100daysofcode</category>
      <category>react</category>
    </item>
    <item>
      <title>Redirect your users to the right language using session storage (i18n)</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Sat, 02 Jan 2021 13:05:51 +0000</pubDate>
      <link>https://dev.to/codetraveling/redirect-your-users-to-the-right-language-using-session-storage-i18n-1la</link>
      <guid>https://dev.to/codetraveling/redirect-your-users-to-the-right-language-using-session-storage-i18n-1la</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a freelancer living and working in Japan, I had been asked many times in the past if I could translate &lt;a href="https://larsbehrenberg.com" rel="noopener noreferrer"&gt;my website&lt;/a&gt; to Japanese. And so finally, at the beginning of December, &lt;strong&gt;I created a Japanese and German version of my so far English website&lt;/strong&gt;. It was a lot of fun testing different ways of doing this and if you are curious and are thinking of doing something similar yourself, I can highly recommend using Gatsby with &lt;a href="https://prismic.io/" rel="noopener noreferrer"&gt;Prismic&lt;/a&gt; as CMS!&lt;/p&gt;

&lt;p&gt;However, after running my new website for a while, &lt;strong&gt;I started getting feedback from my users&lt;/strong&gt; that it would be nice to be redirected to your "correct" language on page load. Instead of having to choose the language yourself after everything is already loaded.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will learn &lt;strong&gt;how to redirect your users to their "correct" language&lt;/strong&gt; and then use &lt;strong&gt;session storage as a memory&lt;/strong&gt;, so that the user can still access other languages without being forcibly redirected every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Set up your path structure &lt;/li&gt;
&lt;li&gt; Redirect your user on page load &lt;/li&gt;
&lt;li&gt; Use session storage as memory &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up your path structure
&lt;/h2&gt;

&lt;p&gt;Of course, there are many different ways to solve this issue of redirecting your users and in some, you might not even want to use something like session storage as memory. However, in my case I wanted the user to know that there are different languages and then even let the user choose which language to access after he had been redirected once to the browser set default language.&lt;/p&gt;

&lt;p&gt;So, the path structure that I chose for my website for that reason looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"/en/page-one"&lt;/li&gt;
&lt;li&gt;"/jp/page-one"&lt;/li&gt;
&lt;li&gt;"/de/page-one"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this type of structure, you can have Gatsby's navigate function simply swap out the language code in the URL. With this out of the way, &lt;strong&gt;let's go and write some code.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Redirect your user on page load
&lt;/h2&gt;

&lt;p&gt;*&lt;em&gt;Note, that in this example we use Gatsby's navigate function, but this can quite simply be replaced with their respective counterparts in React or NextJS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are 3 parts to this example.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;React.useEffect&lt;/strong&gt; to prevent the language redirect function from looping and only run once on page load&lt;/li&gt;
&lt;li&gt;Getting the right URL from the &lt;strong&gt;getRedirectLanguage function&lt;/strong&gt; based on the "navigator" (a browser API to detect the browser's language)&lt;/li&gt;
&lt;li&gt;Passing the correct language key into &lt;strong&gt;Gatsby's navigate function&lt;/strong&gt; to replace the current URL.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;navigate&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="s2"&gt;gatsby&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;getRedirectLanguage&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;`undefined`&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlLang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRedirectLanguage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;urlLang&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// ... your components here&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;IndexPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, you are already set to redirect your user to the correct language. But what if that user doesn't want to be redirected every single time, but instead wants to use a language switch like this one afterward?&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%2F8ecytgva44kpfrx50ngh.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%2F8ecytgva44kpfrx50ngh.png" alt="Choose your language"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use session storage as memory
&lt;/h2&gt;

&lt;p&gt;This is where session storage comes in handy. Look at this example where a simple if clause is added in the &lt;strong&gt;React.useEffect statement&lt;/strong&gt;:&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loggedin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loggedin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// =&amp;gt; then redirect&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlLang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRedirectLanguage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;urlLang&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="na"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, if &lt;strong&gt;sessionStorage&lt;/strong&gt; has not been set, the user won't be redirected and can freely browse the website. But if the user comes onto your website for the first time or for the first time in a while, he will be redirected to his or her default browser language. &lt;strong&gt;Pretty cool, right?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course, this doesn't hold up to some more sophisticated ways of doing this, but for 2 lines of code without using cookies, this saved me a lot of trouble.&lt;/p&gt;

&lt;h2&gt;
  
  
  And that’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/" rel="noopener noreferrer"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to create a Contact Form with Recaptcha hosted on Netlify</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Tue, 29 Dec 2020 23:33:34 +0000</pubDate>
      <link>https://dev.to/codetraveling/how-to-create-a-contact-form-with-recaptcha-hosted-on-netlify-39me</link>
      <guid>https://dev.to/codetraveling/how-to-create-a-contact-form-with-recaptcha-hosted-on-netlify-39me</guid>
      <description>&lt;p&gt;*&lt;em&gt;This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the many handy features of hosting your website on Netlify is the option to have form submissions from your website showing right up in your Netlify dashboard. Or once activated, you can even have email notifications.&lt;/p&gt;

&lt;p&gt;With the free tier on Netlify, this is limited to 100 submissions per site/month, but for most of my clients, this is more than enough. However, I have always found the Netlify Docs to this topic quite confusing, and especially the reCaptcha by Netlify hasn't worked for me.&lt;/p&gt;

&lt;p&gt;So in this tutorial, we will go through the process of implementing a simple contact form with our own Google reCaptcha on Netlify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;As this tutorial is a step by step guide, I recommend you to go through it that way to understand the details, but if you don't mind, you can also find the whole code at the end of this article! This example uses Gatsby and "react-google-recaptcha"&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Getting started with a basic contact form &lt;/li&gt;
&lt;li&gt; Add the Netlify data attribute to your form element &lt;/li&gt;
&lt;li&gt; Get your own reCaptcha key &lt;/li&gt;
&lt;li&gt; Add &lt;em&gt;"react-google-recaptcha"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Don't forget to disable submit unless reCaptcha is approved &lt;/li&gt;
&lt;li&gt; Add email notifications &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started with a basic contact form
&lt;/h2&gt;

&lt;p&gt;To get you started, you will need a basic contact form with a name, email, and message field. And React state will preserve the user's input on change. Notice that in our &lt;strong&gt;handleSubmit&lt;/strong&gt; function we use Gatsby's &lt;strong&gt;navigate&lt;/strong&gt; function to redirect the user to &lt;strong&gt;/thank-you&lt;/strong&gt;. &lt;em&gt;This is the only Gatsby related thing in this example.&lt;/em&gt;&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="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;navigate&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;gatsby&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;ContactForm&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&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;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;

    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="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;form&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;"contact-us"&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/thank-you"&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&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="nt"&gt;noscript&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;This form won’t work with Javascript disabled&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;noscript&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-input"&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;"name"&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-input"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Name / Alias&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;&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;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-input"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&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;"email"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-input"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;&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;textarea&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"textarea"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&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;"message"&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"textarea"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Message&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;buttonn&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&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;form&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add the Netlify data attribute to your form element
&lt;/h2&gt;

&lt;p&gt;Now for the contact form to show in your Netlify dashboard, you will have to include the Netlify data attribute. This way Netlify can know during deployment that there is a form it needs to pay attention to.&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;// ... imports here&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&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="c1"&gt;// ... all the previous code&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;form&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;"contact-us"&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;netlify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;              &lt;span class="c1"&gt;// the Netlify data attribute&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/thank-you"&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... all the inputs and submit button here */&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;form&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Get your own reCaptcha key
&lt;/h2&gt;

&lt;p&gt;Before we get to implement our reCaptcha component in our contact form, we will have to get our free Recaptcha key from Google. Conveniently, as usual, anybody with a Google account can create one &lt;a href="https://www.google.com/recaptcha/admin/create"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ilk1oIry--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/38ig7p3t9hplvkn1kouy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ilk1oIry--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/38ig7p3t9hplvkn1kouy.png" alt="Get your own reCaptcha Key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note here: Make sure to check reCaptcha v2 and "I'm not a robot" tickbox, as this is what we use in our example.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to use the invisible reCaptcha badge, you can find the &lt;a href="https://github.com/dozoisch/react-google-recaptcha#invisible-recaptcha"&gt;documentation here&lt;/a&gt;, or for reCaptcha v3 you can check out &lt;a href="https://www.npmjs.com/package/react-google-recaptcha-v3"&gt;react-google-recaptcha-v3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have registered, you will see your &lt;strong&gt;pair of reCaptcha keys&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FhKrBF8d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zz128njj2wj5b4wgxnhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FhKrBF8d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zz128njj2wj5b4wgxnhc.png" alt="Your own reCaptcha keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In our case, we will only need the SITE KEY!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So go ahead and copy your key. And since it is a public key, we can safely create a variable in our component like so:&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;// ... imports here&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RECAPTCHA_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6LdGSewdkljsdakldasdklj3e2asddaDDS9083&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;ContactForm&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="c1"&gt;// ... previous code here&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// ... previous code here&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;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add &lt;em&gt;"react-google-recaptcha"&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;With our &lt;strong&gt;RECAPTCHA_KEY&lt;/strong&gt; at hand, we can now install the &lt;em&gt;&lt;a href="https://github.com/dozoisch/react-google-recaptcha"&gt;react-google-recaptcha package&lt;/a&gt;&lt;/em&gt;, which will handle most of the reCaptcha stuff for us.&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="nx"&gt;yarn&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;recaptcha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;recaptcha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But to ensure that the reCaptcha talks to our contact form and submissions won't be submitted without reCaptcha's approval, we have to write &lt;strong&gt;a little more code on our own.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'll give you the pieces of code first and afterward, you will find the example with the new parts implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our Recaptcha component:&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Recaptcha&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-google-recaptcha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// ... stuff in between&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// ... stuff&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Recaptcha&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"normal"&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"recaptcha-google"&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Netlify Recatpcha data attribute:&lt;/strong&gt;&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="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;netlify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;recaptcha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;// new Netlify data attribute&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The recaptchaRef:&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recaptchaRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// new Ref for reCaptcha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new &lt;strong&gt;handleSubmit&lt;/strong&gt; function including &lt;strong&gt;reCaptchaValue.&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;And here the whole example:&lt;/strong&gt;&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;// ... other imports here&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Recaptcha&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-google-recaptcha&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;RECAPTCHA_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6LdGSewdkljsdakldasdkljasdda&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;ContactForm&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&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;recaptchaRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// new Ref for reCaptcha&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="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;form&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;"contact-us"&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;netlify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;netlify&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;recaptcha&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;   &lt;span class="c1"&gt;// new Netlify data attribute regarding recaptcha submissions&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/thank-you"&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... all the other inputs here */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Recaptcha&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"normal"&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"recaptcha-google"&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;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&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;form&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Don't forget to disable submit unless reCaptcha is approved
&lt;/h2&gt;

&lt;p&gt;Now after I had come to this point, I noticed that even without submitting reCaptcha, the user would be able to press the submit button and get past the check. This was &lt;strong&gt;no good&lt;/strong&gt;. So I need to ensure that the button was disabled as long as the user hadn't pressed the reCaptcha check. &lt;br&gt;
Luckily &lt;a href="https://github.com/dozoisch/react-google-recaptcha"&gt;react-google-recaptcha&lt;/a&gt; provides us with an onChange function that allows you to set a React state for the submit button, like so:&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;// ... imports here&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&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="c1"&gt;// ... other React State and Ref&lt;/span&gt;

    &lt;span class="c1"&gt;// With this the button is disabled by default, but on Recaptcha change, the form can be submitted&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;buttonDisabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setButtonDisabled&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// ... previous code&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;form&lt;/span&gt;  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... attributes here */&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;Recaptcha&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"normal"&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"recaptcha-google"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setButtonDisabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// disable the disabled 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;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonDisabled&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&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;form&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now on top of this, you might want to consider &lt;strong&gt;adding some CSS&lt;/strong&gt; to let the user know when the button is disabled:&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="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;not-allowed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add email notifications
&lt;/h2&gt;

&lt;p&gt;Last, but not least, we probably don't want to randomly check our Netlify dashboard for submissions, but instead, get automatic email notifications.&lt;/p&gt;

&lt;p&gt;For this login to your &lt;a href="https://app.netlify.com/"&gt;Netlify dashboard&lt;/a&gt;, and in your site settings under Form and Form notification, you can set your preferences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tViA1LuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rokjywewx1h2nkofxt66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tViA1LuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rokjywewx1h2nkofxt66.png" alt="Netlify Email notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find below the final code and with some styling, you have yourself a free and safe, working contact form on Netlify!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final result:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;navigate&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;gatsby&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;Recaptcha&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-google-recaptcha&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;RECAPTCHA_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6LdGSewdkljsdakldasdkljasdda&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;ContactForm&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&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;recaptchaRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&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;buttonDisabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setButtonDisabled&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;recaptchaValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="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;form&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;"contact-us"&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;netlify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;netlify&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;recaptcha&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/thank-you"&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&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="nt"&gt;noscript&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;This form won’t work with Javascript disabled&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;noscript&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-input"&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;"name"&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-input"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Name / Alias&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;&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;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-input"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&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;"email"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-input"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;&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;textarea&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"textarea"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&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;"message"&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;required&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;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"textarea"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Message&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Recaptcha */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Recaptcha&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recaptchaRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"normal"&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"recaptcha-google"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setButtonDisabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="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="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonDisabled&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&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;form&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ContactForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>netlify</category>
      <category>react</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>How to use TypographyJS in NetlifyCMS Previews</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Sat, 26 Dec 2020 13:24:16 +0000</pubDate>
      <link>https://dev.to/codetraveling/how-to-use-typographyjs-in-netlifycms-previews-2479</link>
      <guid>https://dev.to/codetraveling/how-to-use-typographyjs-in-netlifycms-previews-2479</guid>
      <description>&lt;p&gt;*This post was first published on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today is a little different from the usual longer posts and &lt;strong&gt;lot more niche&lt;/strong&gt;. This is about an issue that I ran into recently and thought it would have been nice if somebody had written about it. &lt;strong&gt;Let me explain!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; About NetlifyCMS and Typography.js &lt;/li&gt;
&lt;li&gt; Always read your documentation &lt;/li&gt;
&lt;li&gt; The solution &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About NetlifyCMS and Typography.js
&lt;/h2&gt;

&lt;p&gt;As a &lt;strong&gt;big advocate of the JAMstack&lt;/strong&gt; and in particular Gatsby, I have tried out numerous different CMS and they all have their use cases, but one I often come back to for smaller projects is NetlifyCMS.&lt;/p&gt;

&lt;p&gt;It's free for my use cases and just so easy to use that once set up, it's very easy to teach my clients how to log in and change content on their own.&lt;/p&gt;

&lt;p&gt;There is a lot to say about NetlifyCMS, but that is not what this post is about. This post is about one specific problem that I ran into while I was working on a project recently.&lt;/p&gt;

&lt;p&gt;I had started working on &lt;strong&gt;a Gatsby site with Typography.js &amp;amp; NetlifyCMS&lt;/strong&gt;. Not thinking much about it in the beginning.&lt;/p&gt;

&lt;p&gt;Typography.js is quite a powerful tool to set up your typography and font styling, so it looks nice and consistent throughout the project. (You can learn more about it &lt;a href="https://kyleamathews.github.io/typography.js/"&gt;here&lt;/a&gt;) However, Typography.js uses JavaScript to inject the styling into your project. Once I had started my NetlifyCMS and started preparing custom previews for some of my pages, I realised:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;None of the font styles were applied to the previews within the CMS!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With CSS files you can simply import them to your preview JSX file, but &lt;strong&gt;how would I have to go about injecting Typography.js not only into one custom preview but into all of them?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Always read your documentation
&lt;/h2&gt;

&lt;p&gt;First I started reading through the NetlifyCMS documentation to see if there was &lt;strong&gt;a more general way to add styling sheets to the CMS&lt;/strong&gt; instead of manually importing them to each custom preview. And lo and behold, there was! Here is a snippet from the documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// index.html
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;CMS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPreviewStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/example.css&lt;/span&gt;&lt;span class="dl"&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;But this didn't completely solve my problem and so I started wondering, maybe there was a way to get the CSS styles from Typography.js. Because if you think about it, it ends up being injected as CSS later on anyway, right? &lt;/p&gt;

&lt;p&gt;And I was right. After going through the documentation, Typography.js had a function to output the CSS styling as a string. Just what I needed.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Typography&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;typography&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;typography&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Typography&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseFontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;18px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseLineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.666&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headerFontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Avenir Next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Helvetica Neue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Segoe UI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Helvetica&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sans-serif&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;bodyFontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Georgia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serif&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// See below for the full list of options.&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Output CSS as string.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typographyCSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;typography&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;I have always loved how coding is solving one problem after another and this was exactly that. Now that I knew that I could output my typography styling as a CSS string, I only had to register that styling inside the CMS config file. Here we go:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;typographyCSS&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;../utils/typography&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;CMS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPreviewStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typographyCSS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  It's a CSS string though not a file
&lt;/h3&gt;

&lt;p&gt;However, you might have noticed the &lt;code&gt;{ raw: true }&lt;/code&gt;, the second argument in our registerPreviewStyle function. This is because the function usually expects a CSS file instead of a CSS string. We can fix this by setting this second argument. You can read more about it &lt;a href="https://www.notion.so/How-to-use-TypographyJS-in-NetlifyCMS-Previews-5c90dcfe58cf40d5871dbdce1152ef9b"&gt;here&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s pretty much it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/"&gt;my website&lt;/a&gt; or &lt;a href="https://twitter.com/codetraveling"&gt;Twitter&lt;/a&gt; 🙂  And if you like to read more, make sure to check out my other posts on my &lt;a href="https://blog.larsbehrenberg.com"&gt;blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>100daysofcode</category>
      <category>netlify</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to manage multiple GitHub accounts on your local machine</title>
      <dc:creator>Lars</dc:creator>
      <pubDate>Wed, 23 Dec 2020 08:49:45 +0000</pubDate>
      <link>https://dev.to/codetraveling/how-to-manage-multiple-github-accounts-on-your-local-machine-3gj0</link>
      <guid>https://dev.to/codetraveling/how-to-manage-multiple-github-accounts-on-your-local-machine-3gj0</guid>
      <description>&lt;p&gt;*This post was first published on my &lt;a href="https://blog.larsbehrenberg.com" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One issue that I have run into multiple times in the past is how to manage multiple GitHub accounts on my local machine. Whether you are working on git repositories from multiple clients or you are switching back and forth between personal and the company accounts, almost every developer will eventually encounter this problem. Also for me, I end up looking it up every time I set up a new machine 🤐&lt;/p&gt;

&lt;p&gt;So here is a quick reminder of how to go about this, because it does need a little setup to work nicely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Getting Started 

&lt;ul&gt;
&lt;li&gt; Use SSH keys instead of HTTPS &lt;/li&gt;
&lt;li&gt; Understand the structure of SSH on your local machine &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt; Set up your local SSH config 

&lt;ul&gt;
&lt;li&gt; Generate SSH keys &lt;/li&gt;
&lt;li&gt; Create a config to manage multiple keys &lt;/li&gt;
&lt;li&gt; Register our ssh-agent &lt;/li&gt;
&lt;li&gt; Add the SSH keys to your GitHub accounts &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt; Clone your repo &lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use SSH instead of HTTPS
&lt;/h3&gt;

&lt;p&gt;To set up different accounts on your local machine, &lt;strong&gt;we will be using SSH keys&lt;/strong&gt; instead of the usual HTTPS connection. This has its advantages and disadvantages, and GitHub occasionally changes its opinion on what it recommends best, but here is a quote from the GitHub docs on why we will use SSH keys in this case. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using the SSH protocol, you can connect and authenticate to remote servers and services. With SSH keys, you can connect to GitHub without supplying your username and personal access token at each visit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Github | About SSH&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perfect for us. We don't want to reauthenticate every time and instead commit changes to our repositories as if we never switched accounts. &lt;strong&gt;But how do we set that up?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A quick note here: if you would like to learn more about the differences between HTTPS and SSH, there is an extensive write-up in the &lt;a href="https://help.github.com/articles/generating-ssh-keys" rel="noopener noreferrer"&gt;GitHub docs&lt;/a&gt;! **It's worth checking out!&lt;/em&gt;**&lt;/p&gt;

&lt;h3&gt;
  
  
  Understand the structure of SSH on your local machine
&lt;/h3&gt;

&lt;p&gt;To put it simply: the way this will work is to create unique keys &lt;strong&gt;(SSH keys)&lt;/strong&gt; on your local machine that we will then &lt;strong&gt;add to your Github accounts.&lt;/strong&gt; GitHub won't have to look up your login credentials every time then and instead can verify you by your SSH key. &lt;strong&gt;Sound pretty good, right?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But where do the keys get stored on your local machine?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a folder called &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt;. This is where our setup will happen. Instead of having to set up configuration every time we clone from one of our accounts, once we have made our SSH setup in this folder, we just clone and commit to repositories from different accounts without ever thinking about having to switch accounts on your local machine!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up your local SSH config
&lt;/h2&gt;

&lt;p&gt;If you were to look for your &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt; folder, you might notice that it doesn't exist yet, if for example you never created any keys previously. But instead of creating the folder now ourselves, let our machine do that for us. We start by creating our first key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate SSH keys
&lt;/h3&gt;

&lt;p&gt;When we create SSH keys on our machine, it automatically generates some files and configurations for us. &lt;em&gt;In this tutorial, we will assume you haven't set up any SSH keys yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We get started with the command that will generate the first key:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be prompted and asked to enter the folder/file name you want to go with. &lt;strong&gt;Press ENTER to go with the default location and generate the&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;folder.&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%2Ftcsr58h658w0bdg5k7q5.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%2Ftcsr58h658w0bdg5k7q5.png" alt="Enter custom file name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt; folder, with the just created SSH key. Let's use this default key for our personal account.&lt;/p&gt;

&lt;p&gt;Next up is creating a key for our work account. (You can repeat this process for as many keys as necessary) &lt;strong&gt;And for this we will have to specify the key with some flags.&lt;/strong&gt; "-C" adds a comment/tag and -f specifies the name of the file we want to save the key to.&lt;/p&gt;

&lt;p&gt;Go into your &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create your next key with custom flags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"email@githubworkemail.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"id_rsa_workname"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To dive deeper, here is a list of the different flags you can add:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ssh.com/ssh/keygen/#command-and-option-summary" rel="noopener noreferrer"&gt;List of flags for SSH-keygen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To double-check that all of your keys are there, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a config to manage multiple keys
&lt;/h3&gt;

&lt;p&gt;Now that we have created our keys, we need a configuration file that knows which key to use when we access a repo of one of our GitHub accounts.&lt;/p&gt;

&lt;p&gt;For this inside our &lt;strong&gt;&lt;em&gt;~/.ssh&lt;/em&gt;&lt;/strong&gt; folder, we create and open a &lt;strong&gt;&lt;em&gt;config&lt;/em&gt;&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/.ssh/config &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; code ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here we define our different accounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# personal account&lt;/span&gt;
Host github.com
   HostName github.com
   User git
   IdentityFile ~/.ssh/id_rsa

&lt;span class="c"&gt;# work account 1&lt;/span&gt;
Host github.com-workname
   HostName github.com
   User git
   IdentityFile ~/.ssh/id_rsa_workname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things are important to note here:&lt;/p&gt;

&lt;p&gt;The host, which we will need to remember later when we get our SSH links from GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Host github.com-workname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the identity file, to make sure it points to the correct SSH key that we created before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;IdentityFile ~/.ssh/id_rsa_workname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Register our ssh-agent
&lt;/h3&gt;

&lt;p&gt;Now to keep track of our different SSH keys and their configurations, there is a service called "ssh-agent". It is essentially the key manager for SSH.&lt;/p&gt;

&lt;p&gt;For our purposes, we need to know 3 different commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add &lt;span class="nt"&gt;-D&lt;/span&gt;              // removes all currently registered ssh keys from the ssh-agent
ssh-add &lt;span class="nt"&gt;-l&lt;/span&gt;              // lists all currently &lt;span class="k"&gt;in &lt;/span&gt;the ssh-agent registered ssh keys
ssh-add ~/.ssh/id_rsa   // adds the specified key to the ssh-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you haven't configured any keys previously your ssh-agent has most likely not registered any keys, but let's be completely sure 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;ssh-add &lt;span class="nt"&gt;-D&lt;/span&gt;              // removes all currently registered ssh keys from the ssh-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up is registering our keys with their ids:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/id_rsa &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ssh-add ~/.ssh/id_rsa_workname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Done!&lt;/strong&gt; With this, our local machine is set up and all that is left to do is to register our keys in GitHub and clone our first repo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the SSH keys to your GitHub accounts
&lt;/h2&gt;

&lt;p&gt;There are two steps to this. First, copy the correct key and second, add the key in your dashboard on GitHub.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Copying the correct key.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pbcopy &amp;lt; ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This will copy your &lt;strong&gt;public key&lt;/strong&gt; to your clipboard&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the key in your dashboard at &lt;a href="https://github.com/settings/keys" rel="noopener noreferrer"&gt;https://github.com/settings/keys&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fk5smn4rsug1xlbae354g.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%2Fk5smn4rsug1xlbae354g.png" alt="GitHub add a SSH key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Login into your work GitHub account and repeat this process with your work SSH key.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone your repo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important to note!&lt;/strong&gt;&lt;br&gt;
The reason why your computer knows which SSH key to use, is because we defined the URL in our config file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that for our work repositories, when we clone a repo from the account, like so:&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%2Fdlxg28bs0ie9lnatv6cm.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%2Fdlxg28bs0ie9lnatv6cm.png" alt="Choose SSH link in GitHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We have to change the URL from:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;git@&lt;strong&gt;&lt;em&gt;github.com&lt;/em&gt;&lt;/strong&gt;:workname/repo.git ⇒ git@&lt;strong&gt;&lt;em&gt;github.com-workname&lt;/em&gt;&lt;/strong&gt;:workname/repo.git&lt;/p&gt;

&lt;p&gt;The same URL we have previously defined in our &lt;strong&gt;&lt;em&gt;~/.ssh/config&lt;/em&gt;&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;**&lt;/span&gt;Host github.com-workname  // HERE&lt;span class="k"&gt;**&lt;/span&gt;
   HostName github.com
   User git
   IdentityFile ~/.ssh/id_rsa_workname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With this, you can now clone your repositories and get going! Back to coding, I'd say!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s it!
&lt;/h2&gt;

&lt;p&gt;Thanks so much for reading this far and feel free to reach out to me anytime, on &lt;a href="https://larsbehrenberg.com/" rel="noopener noreferrer"&gt;my website&lt;/a&gt; or on &lt;a href="https://twitter.com/codetraveling" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 🙂&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
