<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ifeoma Imoh</title>
    <description>The latest articles on Forem by Ifeoma Imoh (@iphiee_oma).</description>
    <link>https://forem.com/iphiee_oma</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%2F291532%2Fc1227388-f6b7-43de-8530-75b1d7c0f07b.jpg</url>
      <title>Forem: Ifeoma Imoh</title>
      <link>https://forem.com/iphiee_oma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/iphiee_oma"/>
    <language>en</language>
    <item>
      <title>Remove Image Background With Cloudinary and Pixelz: A Tutorial</title>
      <dc:creator>Ifeoma Imoh</dc:creator>
      <pubDate>Wed, 06 Apr 2022 10:57:08 +0000</pubDate>
      <link>https://forem.com/iphiee_oma/remove-image-background-with-cloudinary-and-pixelz-a-tutorial-23f6</link>
      <guid>https://forem.com/iphiee_oma/remove-image-background-with-cloudinary-and-pixelz-a-tutorial-23f6</guid>
      <description>&lt;p&gt;For all that images are an essential communication medium, their background is just as important because a noisy background tends to draw attention away from images. To resolve that issue, replace the original background with an artificial one for various contexts, such as colored T-shirts, webpage headers, etc.&lt;/p&gt;

&lt;p&gt;This tutorial describes how to remove the background of an image with &lt;a href="https://cloudinary.com/"&gt;Cloudinary&lt;/a&gt; and &lt;a href="https://www.pixelz.com/"&gt;Pixelz&lt;/a&gt;. You start with building a React app that uploads an image and then proceeds to remove its background. Afterwards, hook into the process and build a mechanism that notifies you by email when the removal process is complete. &lt;/p&gt;

&lt;p&gt;Keep in mind the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You must be on a &lt;strong&gt;paid Cloudinary plan&lt;/strong&gt; to access the features required, which are a premium Cloudinary offering. You must also subscribe to Cloudinary’s &lt;a href="https://cloudinary.com/console/c-e70f9191c52089ff010d34428bdf68/addons#remove_the_background"&gt;Pixelz&lt;/a&gt; add-on.&lt;/li&gt;
&lt;li&gt;Background removal is carried out asynchronously by a team of human experts, who could take up to 24 hours to complete the task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A  &lt;a href="https://codesandbox.io/s/remove-image-background-with-cloudinary-and-pixelz-dmvdps"&gt;demo&lt;/a&gt; is on CodeSandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Project
&lt;/h2&gt;

&lt;p&gt;First, set up the project:&lt;/p&gt;

&lt;p&gt;Create a React app with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npx create-react-app image_background_remover
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the project dependencies:&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;antd @ant-design/icons axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the CSS for &lt;code&gt;antd&lt;/code&gt; by adding &lt;code&gt;~antd/dist/antd.css&lt;/code&gt;  to the &lt;code&gt;App.css&lt;/code&gt; file in your &lt;code&gt;src&lt;/code&gt; directory:&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="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"~antd/dist/antd.css"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up Cloudinary
&lt;/h2&gt;

&lt;p&gt;First, sign up for a free Cloudinary account. Displayed on your account’s Management Console (aka Dashboard) are important details: your cloud name, API key, etc.&lt;/p&gt;

&lt;p&gt;Since you’ll be sending images to Cloudinary through unsigned &lt;code&gt;POST&lt;/code&gt; requests, create an unsigned &lt;a href="https://cloudinary.com/documentation/upload_presets"&gt;upload preset&lt;/a&gt;, as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the Management Console, choose  &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Upload&lt;/strong&gt; for the page with &lt;a href="https://cloudinary.com/console/settings/upload"&gt;upload settings&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll to the &lt;strong&gt;Upload presets&lt;/strong&gt; section and click &lt;strong&gt;Add upload preset&lt;/strong&gt; at the bottom of the section. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the page that’s displayed, choose &lt;strong&gt;Unsigned&lt;/strong&gt; from the pull-down menu under &lt;strong&gt;Signing Mode&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Media analysis and AI&lt;/strong&gt; in the left-navigation area and, on the page that’s displayed, choose &lt;strong&gt;Pixelz&lt;/strong&gt; from the pull-down menu under &lt;strong&gt;Background removal&lt;/strong&gt;. Click &lt;strong&gt;Save&lt;/strong&gt; at the top.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Kuot59P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1647492916748_CleanShot%2B2022-03-17%2Bat%2B08.54.162x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Kuot59P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1647492916748_CleanShot%2B2022-03-17%2Bat%2B08.54.162x.png" alt="Screenshot of upload preset page" width="880" height="407"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the name of the upload preset you just created for later use.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, create environment variables to hold the details of your Cloudinary account. Follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file called &lt;code&gt;.env&lt;/code&gt; at the root of the project with the content below. Be sure to replace the two variables after the &lt;code&gt;=&lt;/code&gt; symbol with their values.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;REACT_APP_CLOUD_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nx"&gt;REACT_APP_UPLOAD_PRESET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;unsigned&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;preset&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two settings will serve as the default if you set up the project on another system. To update your local environment, create a copy of the &lt;code&gt;.env&lt;/code&gt; file by running this command:&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;cp&lt;/span&gt; .env .env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, this local file resides in the &lt;code&gt;.gitignore&lt;/code&gt; folder, mitigating the security risk of inadvertently exposing secret credentials to the public. You can update the &lt;code&gt;.env.local&lt;/code&gt; file with your Cloudinary account’s cloud name and the upload preset you created earlier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the root directory of your project, create a folder named &lt;code&gt;utility&lt;/code&gt; for the helper classes for your components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In your &lt;code&gt;src&lt;/code&gt; folder, create a file named &lt;code&gt;cloudinaryConfig.js&lt;/code&gt; for accessing the environment variables and for preventing repeated &lt;code&gt;process.env.&lt;/code&gt; calls throughout the project. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the code below to the &lt;code&gt;cloudinaryConfig.js&lt;/code&gt; file. Be sure to replace the two variables, &lt;code&gt;React_app_cloud_name&lt;/code&gt; and &lt;code&gt;React_app_upload_preset&lt;/code&gt;, with their values.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloudName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;React_app_cloud_name&lt;/span&gt;&lt;span class="p"&gt;;&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;uploadPreset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;React_app_upload_preset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Helper Class for API Requests
&lt;/h2&gt;

&lt;p&gt;Now write a helper function for uploading an image to Cloudinary before starting the background-removal process. In the &lt;code&gt;utility&lt;/code&gt; folder, create a file named &lt;code&gt;api.js&lt;/code&gt; with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&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;axios&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;cloudName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uploadPreset&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;./cloudinaryConfig&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploadImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;successCallback&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://api.cloudinary.com/v1_1/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cloudName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/image/upload`&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;data&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;FormData&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="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&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="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;upload_preset&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uploadPreset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;axios&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&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;data&lt;/span&gt;&lt;span class="p"&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;multipart/form-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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;successCallback&lt;/span&gt;&lt;span class="p"&gt;(&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;data&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;The &lt;code&gt;uploadImage&lt;/code&gt; function uploads the file as specified to Cloudinary by making a &lt;code&gt;POST&lt;/code&gt; request to Cloudinary along with the file name and the name of the upload preset you created earlier. On successful completion of the request, &lt;code&gt;uploadImage&lt;/code&gt; executes the callback, passing the Cloudinary response as a function parameter.&lt;/p&gt;

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

&lt;p&gt;Next, create the components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In your project's &lt;code&gt;src&lt;/code&gt; folder, create a folder called &lt;code&gt;components&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;src/components&lt;/code&gt; folder, create a file called &lt;code&gt;ImageSelector.js&lt;/code&gt; with this code:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Upload&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;antd&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;UploadOutlined&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;@ant-design/icons&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;ImageSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;setImage&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;onRemove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;beforeUpload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedImage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;showUploadList&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="na"&gt;maxCount&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="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Upload&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;icon&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;UploadOutlined&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Select&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Upload&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ImageSelector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By way of explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;ImageSelector&lt;/code&gt; component takes &lt;code&gt;setImage&lt;/code&gt;, a callback function that updates the app state with the latest image you uploaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By returning &lt;code&gt;false&lt;/code&gt; in the &lt;code&gt;beforeUpload&lt;/code&gt; key of &lt;code&gt;props&lt;/code&gt;, you’ve disabled the default behavior of the &lt;code&gt;[Upload](https://ant.design/components/upload/)&lt;/code&gt; component, which uploads the selected file to the URL as specified. You’ve also restricted the maximum number of files to 1.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Replace the content of your &lt;code&gt;src/App.js&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&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;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Col&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;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;antd&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;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ImageSelector&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ImageSelector&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;uploadImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./util/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;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;isUploading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsUploading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;formItemLayout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;labelCol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;wrapperCol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&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;onFailedSubmission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&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;onFinish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&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;image&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="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;message&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You need to upload an image first&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setIsUploading&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="nx"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;successCallback&lt;/span&gt;&lt;span class="p"&gt;:&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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;setIsUploading&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Image uploaded successfully.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1%&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50%&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&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;formItemLayout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;onFinish&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onFinish&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;onFinishFailed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onFailedSubmission&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;autoComplete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Col&lt;/span&gt; &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10px&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ImageSelector&lt;/span&gt; &lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Col&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="nx"&gt;wrapperCol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;htmlType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isUploading&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;Submit&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Form.Item&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By way of explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’ve declared two state variables: one for the uploaded image and the other as a depiction of whether the image is being uploaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;formItemLayout&lt;/code&gt; is an object that contains the size specifications for the &lt;code&gt;label&lt;/code&gt; columns in the form to be created. Failure to validate the submitted form triggers the &lt;code&gt;onFailedSubmission&lt;/code&gt; function. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ve logged errors to Cloudinary’s Management Console, which displays a warning message if errors are present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the data in the submitted form is valid, the &lt;code&gt;onFinish&lt;/code&gt; function is called. Absent a selection of an image, &lt;code&gt;onFinish&lt;/code&gt; displays an error message. Otherwise, the &lt;code&gt;uploadImage&lt;/code&gt; function declared in &lt;code&gt;api.js&lt;/code&gt; uploads the image to Cloudinary . &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On a successful upload, &lt;code&gt;uploadImage&lt;/code&gt; displays a message to that effect in Cloudinary’s Management Console .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ve rendered the &lt;code&gt;ImageSelector&lt;/code&gt; component so that you can select an image for upload. On such a selection and a click of the Submit button, the &lt;code&gt;onFinish&lt;/code&gt; function uploads the image to Cloudinary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now run the app with this command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;By default, the app is at &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt;. Upon successful selection and upload of an image, this response is displayed in the Management Console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://res.cloudinary.com/&amp;lt;cloud_name&amp;gt;/image/upload/v1647108022/&amp;lt;public_id&amp;gt;.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;secure_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://res.cloudinary.com/&amp;lt;cloud_name&amp;gt;/image/upload/v1647108022/&amp;lt;public_id&amp;gt;.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background_removal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove_the_background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
             &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, the background-removal process is asynchronous. Once it’s complete, the edited version replaces the original image and is accessible through Cloudinary’s Management console or content delivery network (CDN).&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Status Notifications
&lt;/h2&gt;

&lt;p&gt;To keep checking the URL in the response for the updated image is an unproductive use of time. Instead, leverage the Cloudinary feature that notifies you by email when an editing process is a wrap. To that end, build an API that handles notifications from Cloudinary and that emails you the edited version of the uploaded image.&lt;/p&gt;

&lt;p&gt;First, create a project folder named &lt;code&gt;cloudinaryNotificationHandler&lt;/code&gt; for these two API files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server.js&lt;/code&gt;, which handles the incoming requests and sends the appropriate response. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helper.js&lt;/code&gt;, which performs such tasks as downloading images and sending emails.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up the Mailing Process
&lt;/h2&gt;

&lt;p&gt;Perform these steps to establish the email-notification process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install and add &lt;a href="https://nodemailer.com/about/"&gt;Nodemailer&lt;/a&gt; to your project:
&lt;/li&gt;
&lt;/ul&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;nodemailer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Feel free to use another Simple Mail Transfer Protocol (SMTP) mail provider of your choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set up &lt;a href="https://mailtrap.io/"&gt;Mailtrap&lt;/a&gt; by &lt;a href="https://mailtrap.io/register/signup?ref=header"&gt;creating a Mailtrap account&lt;/a&gt;. If you already have one, &lt;a href="https://mailtrap.io/signin"&gt;log in&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the &lt;strong&gt;Show Credentials&lt;/strong&gt; link in the &lt;strong&gt;SMTP Settings&lt;/strong&gt; tab, copy your user name and password, and save them for a later step.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5XHrimIl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648578279093_CleanShot%2B2022-03-29%2Bat%2B22.23.242x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5XHrimIl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648578279093_CleanShot%2B2022-03-29%2Bat%2B22.23.242x.png" alt="Screenshot of SMTP settings tab on Mailtrap" width="880" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Helper Functions
&lt;/h2&gt;

&lt;p&gt;Add the following to your &lt;code&gt;helper.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&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;nodemailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nodemailer&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;buildCloudinaryUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicId&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;cloudName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT YOUR CLOUD NAME HERE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`https://res.cloudinary.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cloudName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/image/upload/v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;version&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;publicId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg`&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;downloadImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createWriteStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request Failed With a Status Code: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nodemailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smtp.mailtrap.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT YOUR MAILTRAP USER name HERE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT YOUR MAILTRAP PASSWORD HERE&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;from-example@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-example@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Image Background Removal Complete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
          &amp;lt;p&amp;gt; Hi there!!!&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;The image processing is complete, here are the notification details &amp;lt;/p&amp;gt;
          &amp;lt;code&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/code&amp;gt;
          `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&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;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;reject&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="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;downloadImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buildCloudinaryUrl&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By way of explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Based on two parameters—the image URL and the file path in which to save the image—the &lt;code&gt;downloadImage&lt;/code&gt; function makes a &lt;code&gt;GET&lt;/code&gt; request to the URL and writes the content of the response to that path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also based on two parameters—&lt;code&gt;content&lt;/code&gt;, the information sent by Cloudinary; and &lt;code&gt;filepath&lt;/code&gt;, the path in which the edited image resides—the &lt;code&gt;sendMail&lt;/code&gt; function sets up a Nodemailer transport and sends an email with the edited image as an attachment.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the following to your &lt;code&gt;server.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&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;downloadImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buildCloudinaryUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./helper&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;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&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;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&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;requestListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffers&lt;/span&gt; &lt;span class="o"&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await&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;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;buffers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffers&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;public_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secure_url&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parsedData&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;filepath&lt;/span&gt; &lt;span class="o"&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;public_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;fileUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buildCloudinaryUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;public_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;downloadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setHeader&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/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;204&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestListener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;host&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;port&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’ve declared a request listener for handling requests, i.e., extract their content and then retrieve the public ID and version specified there. The &lt;code&gt;buildCloudinaryUrl&lt;/code&gt; function builds the URL for the edited image so that it’s in JPEG format with a &lt;code&gt;.jpg&lt;/code&gt; file extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;downloadImage&lt;/code&gt; function downloads the image; the &lt;code&gt;sendMail&lt;/code&gt; helper function sends the image by email. Finally, a 204 response is returned, informing you that the response contains no content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now serve the app by running this command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, test the setup by sending the sample &lt;code&gt;POST&lt;/code&gt; request generated by Cloudinary for your API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification_type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info_kind&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pixelz&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info_status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wood_chair&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uploaded_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2014-10-26T11:35:22Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1414316122&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://res.cloudinary.com/demo/image/upload/v1393688588/wood_chair.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;secure_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://res.cloudinary.com/demo/image/upload/v1393688588/wood_chair.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;etag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a56e9e88c2add15cac1775c1f687bf73&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;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JvohQ71Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648477075085_CleanShot%2B2022-03-28%2Bat%2B18.17.122x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JvohQ71Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648477075085_CleanShot%2B2022-03-28%2Bat%2B18.17.122x.png" alt="Screenshot of inbox page on Mailtrap" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything looks good, except that your setup is local. The next section describes how to expose that local setup to Cloudinary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifying the Port Number Through Ngrok
&lt;/h2&gt;

&lt;p&gt;To expose your app, which is running, to the internet, leverage the cross-platform app &lt;a href="https://ngrok.com/"&gt;Ngrok&lt;/a&gt;. Follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download the &lt;a href="https://ngrok.com/download"&gt;Ngrok executable file&lt;/a&gt; and unzip it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the Ngrok &lt;code&gt;http&lt;/code&gt; command to specify the port number you’d like to be exposed. Since your API runs on port 8000, type:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;Afterwards, start Ngrok, which will display in your terminal the public URL of your tunnel and the status and metrics that pertain to the connections made over your tunnel. See this example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GbRgxc6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648476756274_CleanShot%2B2022-03-28%2Bat%2B18.12.042x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GbRgxc6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_7B100199EE60C13BD0E39958888CD27528AD9A232FB9EEA476835B48B0A44BB7_1648476756274_CleanShot%2B2022-03-28%2Bat%2B18.12.042x.png" alt="Screenshot of terminal showing Ngrok UI" width="880" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifying the Notification URL
&lt;/h2&gt;

&lt;p&gt;Now that you’ve built the tunnel and your app is running, configure your upload preset in Cloudinary so that the preset will let you know when the image-removal process is complete. Here’s what to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the Management Console, choose &lt;strong&gt;Settings &amp;gt; Upload&lt;/strong&gt; and scroll to the &lt;strong&gt;Upload presets&lt;/strong&gt; section. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Edit&lt;/strong&gt; next to the upload preset you created earlier and then click &lt;strong&gt;Upload Manipulations&lt;/strong&gt; in the left-navigation area. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;strong&gt;Notification URL&lt;/strong&gt; text field, paste the URL displayed on the Ngrok terminal and click &lt;strong&gt;Save&lt;/strong&gt; at the top.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the &lt;a href="https://github.com/ifeoma-imoh/remove-image-background-with-pixelz-and-cloudinary"&gt;complete code&lt;/a&gt; of this project on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summing Up
&lt;/h2&gt;

&lt;p&gt;This tutorial walks you through the procedures for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove the background of an image with Cloudinary and Pixelz.&lt;/li&gt;
&lt;li&gt;Build a simple Node HTTP server to handle &lt;code&gt;POST&lt;/code&gt; requests and send notifications by email—no need to refresh pages or worry about when background removal will be complete. Pretty neat, right?&lt;/li&gt;
&lt;li&gt;Link a &lt;a href="http://localhost/"&gt;localhost&lt;/a&gt; app to your Cloudinary account’s Management Console with Ngrok. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For further reference, see the documentation on &lt;a href="https://cloudinary.com/documentation/remove_the_background_image_editing_addon"&gt;Cloudinary’s Pixelz add-on&lt;/a&gt;, &lt;a href="https://mailtrap.io/"&gt;Mailtrap&lt;/a&gt;, and &lt;a href="https://ngrok.com/docs"&gt;Ngrok&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understand JavaScript Abstract Operations in 7 Minutes.
</title>
      <dc:creator>Ifeoma Imoh</dc:creator>
      <pubDate>Mon, 01 Feb 2021 12:19:09 +0000</pubDate>
      <link>https://forem.com/iphiee_oma/understand-javascript-abstract-operations-in-7-minutes-1951</link>
      <guid>https://forem.com/iphiee_oma/understand-javascript-abstract-operations-in-7-minutes-1951</guid>
      <description>&lt;p&gt;To help you understand better, let’s quickly revisit types in JavaScript. Variables in JavaScript do not have types; values do. JavaScript has eight basic value data types, and they are divided into two categories, primitive and non-primitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primitive Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Undefined&lt;/li&gt;
&lt;li&gt;Null&lt;/li&gt;
&lt;li&gt;Boolean&lt;/li&gt;
&lt;li&gt;String&lt;/li&gt;
&lt;li&gt;Symbol&lt;/li&gt;
&lt;li&gt;Number&lt;/li&gt;
&lt;li&gt;BigInt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-Primitive Types (Reference types):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object&lt;/li&gt;
&lt;li&gt;Array&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Function&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Arrays&lt;/code&gt;  and  &lt;code&gt;functions&lt;/code&gt;  are subtypes of the  &lt;code&gt;object&lt;/code&gt;  type.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One major difference between primitive and non-primitive values is that primitive values are immutable after creation while non-primitive values are mutable. &lt;/p&gt;

&lt;p&gt;Let’s take an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Let's alter the value of the string assigned to the variable person.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ifeoma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;// Here it simply made a copy and then altered the copied value.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// IFEOMA&lt;/span&gt;
&lt;span class="c1"&gt;// It didn't change the original value.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//  ifeoma&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the example above, when we tried to alter the value, it only made a copy of the variable &lt;code&gt;person&lt;/code&gt;  and changed it, but it didn’t change the already existing  &lt;code&gt;string&lt;/code&gt;  value because it is a primitive.&lt;/p&gt;

&lt;p&gt;On the other hand, the variable assigned to a primitive value can be changed. Therefore, it can be reassigned so that it points to a new value but the existing value it holds cannot be changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ifeoma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sylvia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// sylvia&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we assigned a new  &lt;code&gt;string&lt;/code&gt;  value to the variable  &lt;code&gt;person&lt;/code&gt;  so that it no longer points to the initial  &lt;code&gt;string&lt;/code&gt;  value  &lt;code&gt;ifeoma&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Let’s try to mutate a non-primitive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jay Pritchet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Phil Dunphy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Claire Pritchet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// [ "Jay Pritchet", "Phil Dunphy", "Claire Pritchet" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we made  &lt;code&gt;array&lt;/code&gt;  a reference to  &lt;code&gt;array2&lt;/code&gt; . Emphasis on reference, which means that even after we modified the data in &lt;code&gt;array&lt;/code&gt; by adding a new item to it, logging  &lt;code&gt;array2&lt;/code&gt;  shows the new item added to  &lt;code&gt;array&lt;/code&gt; . &lt;br&gt;
This is because the variable &lt;code&gt;array2&lt;/code&gt; is referencing the address of the variable &lt;code&gt;array&lt;/code&gt;. &lt;br&gt;
This behavior is expected from all non-primitive value types.&lt;/p&gt;

&lt;p&gt;Another difference between primitives and non-primitives is that primitives are stored by value while non-primitives are stored by reference.&lt;/p&gt;

&lt;p&gt;The  &lt;code&gt;typeOf&lt;/code&gt;  operator is a built-in utility used to check the type of value assigned to a javascript variable. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The  &lt;code&gt;typeOf&lt;/code&gt;   operator always returns a string type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s take a look at how values are changed from one type to another.&lt;/p&gt;
&lt;h2&gt;
  
  
  Coercion
&lt;/h2&gt;

&lt;p&gt;Coercion refers to the process of converting values from one type to another(such as  &lt;code&gt;string&lt;/code&gt;  to  &lt;code&gt;number&lt;/code&gt; ).&lt;br&gt;
Using inbuilt functions(&lt;code&gt;Number()&lt;/code&gt;, &lt;code&gt;String()&lt;/code&gt; etc.) you can be obvious about your intention to convert a value from one type to another(explicit coercion) or let Javascript automatically handle the conversion for you(Implicit coercion). &lt;/p&gt;

&lt;p&gt;Coercion always results in either  &lt;code&gt;strings&lt;/code&gt; ,  &lt;code&gt;numbers&lt;/code&gt; , or  &lt;code&gt;booleans&lt;/code&gt; . Understanding coercion will help you avoid problems that can occur in your code.&lt;br&gt;
Let's see some examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implicit Coercion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// 4  JavaScript coerced the string 1 to a number.&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// 0  Javascript coerced the boolean false to 0.&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// 11  The boolean true is coerced to a number 1.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicit Coercion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3 Here we are explicitly converting both strings to numbers first using the Number() method.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fully understand how coercion happens, we need to talk about &lt;strong&gt;Abstract Operations.&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Abstract Operations are the fundamental building block that makes up how we deal with type conversion. - Kyle Simpson                       &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Abstract Operations
&lt;/h2&gt;

&lt;p&gt;According to the ECMAScript specification, abstract operations are not part of the language specification, but they are responsible for performing type conversion in Javascript. Whenever coercion (implicit or explicit) occurs, one or more internal operations, known as abstract operations, are performed. &lt;/p&gt;

&lt;p&gt;We will look at these four primary abstract operations, but you can find the rest of them in the &lt;a href="https://tc39.es/ecma262/#sec-abstract-operations"&gt;spec.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ToPrimitive()&lt;/li&gt;
&lt;li&gt;ToString()&lt;/li&gt;
&lt;li&gt;ToNumber()&lt;/li&gt;
&lt;li&gt;ToBoolean() &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ToPrimitive()
&lt;/h2&gt;

&lt;p&gt;When a non-primitive or reference value is used in the context where a primitive is required, the JavaScript engine calls the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  abstract operation. &lt;/p&gt;

&lt;p&gt;When converting non-primitive types to primitives, the abstract operation ToPrimitive() is invoked to handle the operation.&lt;/p&gt;

&lt;p&gt;Let's see how non-primitive values are converted to primitives.&lt;/p&gt;

&lt;p&gt;The spec informs us that the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  abstract operation takes two arguments. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; An &lt;strong&gt;input&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;An optional &lt;strong&gt;&lt;em&gt;PreferredType&lt;/em&gt;&lt;/strong&gt; hint&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;The PreferredType hint can be either one of these -  &lt;code&gt;string&lt;/code&gt; ,  &lt;code&gt;number&lt;/code&gt; ,  &lt;code&gt;default&lt;/code&gt; .                      &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are performing a numeric operation and the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  operation is invoked, &lt;code&gt;number&lt;/code&gt; will be sent as the hint. If you are working with strings, it will send  &lt;code&gt;string&lt;/code&gt;  as the hint. &lt;br&gt;
When  &lt;code&gt;ToPrimitive()&lt;/code&gt; is called with no hint present, it'll send  &lt;code&gt;default&lt;/code&gt;  as a hint, and this will behave as if the hint were  &lt;code&gt;number&lt;/code&gt;  (unless it's a  &lt;code&gt;Date&lt;/code&gt;  which defaults to  &lt;code&gt;string&lt;/code&gt; ).&lt;/p&gt;

&lt;p&gt;If the argument is already a primitive value, then it will be returned without conversion. Let's take a look at how the ToPrimitive algorithm works.&lt;/p&gt;

&lt;p&gt;There are two methods available on every object type used to convert them from non-primitives to primitives:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;valueOf() — This is to retrieve the primitive value associated with an object.&lt;/li&gt;
&lt;li&gt;toString() &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Number Algorithm&lt;/strong&gt;&lt;br&gt;
If the hint is  &lt;code&gt;number&lt;/code&gt; , it calls the &lt;code&gt;valueOf()&lt;/code&gt;  function first, and if the returned value is primitive, it'll use it. If the object has no primitive value,  &lt;code&gt;valueOf()&lt;/code&gt;   returns the object back then the  &lt;code&gt;toString()&lt;/code&gt;  function gets called. Its value will be used if it is primitive; otherwise, it would result in a type error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;String Algorithm&lt;/strong&gt;&lt;br&gt;
If the hint is  &lt;code&gt;string&lt;/code&gt; , the order is reversed compared to the number algorithm. It calls the non-primitive  &lt;code&gt;toString()&lt;/code&gt;  function first, and if it gets a string representation, it'll just use it; otherwise, it'll try the  &lt;code&gt;valueOf()&lt;/code&gt; method to see if the object has any primitive value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default Algorithm&lt;/strong&gt;&lt;br&gt;
If no hint is sent, it sets the default hint to  &lt;code&gt;number&lt;/code&gt; &lt;strong&gt;,&lt;/strong&gt; or it is set to  &lt;code&gt;string&lt;/code&gt;  if it is a  &lt;code&gt;Date&lt;/code&gt; . &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The algorithms within JavaScript are inherently recursive. This means that if the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  operation gets invoked and the return result is not a primitive, it will keep getting invoked until it returns a primitive or an error.   &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  ToString()
&lt;/h2&gt;

&lt;p&gt;This abstract operation takes any value and converts it to a representation of the value in  &lt;code&gt;string&lt;/code&gt;  form.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Argument&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;“null”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undefined&lt;/td&gt;
&lt;td&gt;“undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;“true”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;“false”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“Hi”&lt;/td&gt;
&lt;td&gt;“Hi”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symbol&lt;/td&gt;
&lt;td&gt;Throw a TypeError exception.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As seen above, built-in primitives have natural stringification, but if the  &lt;code&gt;ToString()&lt;/code&gt;  operation is called on an  &lt;code&gt;object&lt;/code&gt;  type, it will invoke the &lt;code&gt;ToPrimitive()&lt;/code&gt; operation, and pass &lt;code&gt;string&lt;/code&gt; as the hint.&lt;/p&gt;

&lt;p&gt;As explained earlier, this will call the  &lt;code&gt;toString()&lt;/code&gt;  first, and if it gets a &lt;code&gt;string&lt;/code&gt; representation, it'll just use it; otherwise, it'll try the  &lt;code&gt;valueOf()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;By default, regular JavaScript objects have their built-in  &lt;code&gt;toString()&lt;/code&gt;  method (located in &lt;a href="https://tc39.es/ecma262/#sec-object.prototype.tostring"&gt;&lt;strong&gt;Object.prototype.toString()&lt;/strong&gt;&lt;/a&gt;) that is called when an object is used in a manner in which a &lt;code&gt;string&lt;/code&gt; is expected and this will return their internal [[Class]] property (e.g [object Object]). &lt;/p&gt;

&lt;p&gt;Unless you specify your &lt;code&gt;toString()&lt;/code&gt; method, if you use an object in a string-like way, the &lt;code&gt;toString()&lt;/code&gt; method on its object prototype will be called. This will return a &lt;code&gt;string&lt;/code&gt; with the [object Type] format where  &lt;code&gt;Type&lt;/code&gt;  is the object type. &lt;/p&gt;

&lt;p&gt;Let’s see an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;obj&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;span class="c1"&gt;// [object Object]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although &lt;code&gt;arrays&lt;/code&gt; are subtypes of the object type, the &lt;code&gt;array&lt;/code&gt; object has a built-in  &lt;code&gt;toString()&lt;/code&gt;  method that overrides the default  &lt;code&gt;Object.toString()&lt;/code&gt;  method and returns a  &lt;code&gt;string&lt;/code&gt;  representation containing each array element separated by a comma. This &lt;code&gt;toString()&lt;/code&gt; method lives on the Array’s prototype  as &lt;code&gt;Array.prototype.toString()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Calling toString() explicitly on an array&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// ""  It returns an empty string.&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;array1&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;span class="c1"&gt;// "1,2,3"  It returns a string containing each element in the array seperated by a comma.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a situation where you want to get the object class, you need to skip the default override behavior of &lt;code&gt;Array.prototype.toString&lt;/code&gt; in favor of &lt;code&gt;Object.prototype.toString()&lt;/code&gt; . &lt;/p&gt;

&lt;p&gt;You have to pass the  &lt;code&gt;array&lt;/code&gt;  in the  &lt;code&gt;call()&lt;/code&gt; method to change the context from &lt;code&gt;Array&lt;/code&gt; to &lt;code&gt;Object&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&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;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="c1"&gt;// [object Array] &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ToNumber()
&lt;/h2&gt;

&lt;p&gt;Whenever we perform a numeric operation, and one or both operands aren't numbers, the  &lt;code&gt;ToNumber()&lt;/code&gt;  abstract operation will be invoked to convert it to a value of type  &lt;code&gt;number&lt;/code&gt; . &lt;br&gt;
Let's see some examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Argument&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“”&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“.”&lt;/td&gt;
&lt;td&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“1”&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BigInt&lt;/td&gt;
&lt;td&gt;Throw a type error exception.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;symbol&lt;/td&gt;
&lt;td&gt;Throw a type error exception.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;1.  &lt;a href="https://tc39.es/ecma262/#sec-toprimitive"&gt;ToPrimitive&lt;/a&gt;(argument, number).&lt;br&gt;2. Return ? &lt;a href="https://tc39.es/ecma262/#sec-tonumber"&gt;ToNumber&lt;/a&gt;(primValue).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As seen from the table above, when  &lt;code&gt;ToNumber()&lt;/code&gt;  is called on a non-primitive (any of the object types) value, it is first converted to its primitive equivalent by invoking  &lt;code&gt;ToPrimitive()&lt;/code&gt; abstract operation and passing  &lt;code&gt;number&lt;/code&gt;  as the PreferredType hint.&lt;br&gt;
The return value from the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  operation will then be coerced into a  &lt;code&gt;number&lt;/code&gt;  by the  &lt;code&gt;ToNumber()&lt;/code&gt; abstract operation. If it still doesn't result in a primitive value, it throws an error.&lt;/p&gt;

&lt;p&gt;Let's take an array with an empty string as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ToPrimitive&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="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// It first calls the ToPrimitive abstract operation on it and pass number as the hint.&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// [""]  Because  the hint is number, it calls valueOf first and this basically returns itself. So we still have the array with an empty string which isn’t a primitive.&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// ""   It then calls the toString() function next and this will end up producing an empty string "".&lt;/span&gt;

&lt;span class="nx"&gt;ToNumber&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="c1"&gt;// 0   Next it calls ToNumber() and passes the empty string "" as an argument. As seen from the table above, that would result to 0.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ToBoolean()
&lt;/h2&gt;

&lt;p&gt;The abstract operation   &lt;code&gt;ToBoolean()&lt;/code&gt;  is called to convert an argument to a Boolean type whenever we use a value that is not  &lt;code&gt;Boolean&lt;/code&gt;  in a place that needs a   &lt;code&gt;Boolean&lt;/code&gt; . The  &lt;code&gt;ToBoolean()&lt;/code&gt;  abstract operation does not invoke the  &lt;code&gt;ToPrimitive()&lt;/code&gt;  or any of the other abstract operations.&lt;br&gt;
It just checks to see if the value is either falsy or not. There is a lookup table in the spec that defines a list of values that will return  &lt;code&gt;false&lt;/code&gt;  when coerced to a  &lt;code&gt;boolean&lt;/code&gt; . They are called falsy values.  &lt;/p&gt;

&lt;p&gt;These are the falsy values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Argument Type&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NaN&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-0&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“”&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Values that are not on the list of falsy values are truthy values.&lt;/p&gt;

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

&lt;p&gt;Languages that take the first position about their rules are referred to as "strongly typed" because they are strict about not allowing you to break the rules.&lt;br&gt;
Since JavaScript is not one of them, it is referred to as weakly or loosely typed because it gives room for a lot of flexibility in terms of implicit coercion, and you do not have to specify the type of your variables explicitly.&lt;/p&gt;

&lt;p&gt;Like any other language, Javascript has its rules, and the rules that govern the type system of a language exist to help us. It is up to us to learn them to avoid unnecessary mistakes.&lt;/p&gt;

&lt;p&gt;Thank you! I hope you enjoyed reading as much as I enjoyed writing ❤️.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>coercion</category>
      <category>abstractoperations</category>
      <category>javascripttypes</category>
    </item>
    <item>
      <title>A Complete Git and GitHub Workflow Using VS Code Only</title>
      <dc:creator>Ifeoma Imoh</dc:creator>
      <pubDate>Wed, 02 Dec 2020 11:07:24 +0000</pubDate>
      <link>https://forem.com/iphiee_oma/a-complete-git-and-github-workflow-using-vs-code-only-2nel</link>
      <guid>https://forem.com/iphiee_oma/a-complete-git-and-github-workflow-using-vs-code-only-2nel</guid>
      <description>&lt;p&gt;I recently discovered that I could integrate Github into my Visual Studio Code. This means that I can create pull requests, create issues, clone repositories, collaborate with others, etc., without leaving VS Code. I was excited and decided to write about it. In this article, we’ll go over how to complete some of the things we do on Github right in VS Code.&lt;/p&gt;

&lt;p&gt;We will cover the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Setup &lt;/li&gt;
&lt;li&gt;
Clone a project &lt;/li&gt;
&lt;li&gt;Stage and commit&lt;/li&gt;
&lt;li&gt;Create a new branch&lt;/li&gt;
&lt;li&gt;Stash changes&lt;/li&gt;
&lt;li&gt;
Push changes &lt;/li&gt;
&lt;li&gt;View commit timeline&lt;/li&gt;
&lt;li&gt;
Create pull requests &lt;/li&gt;
&lt;li&gt;
Pull from a remote repository &lt;/li&gt;
&lt;li&gt;
Add a remote repository &lt;/li&gt;
&lt;li&gt;
Publish a new project &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;I’m assuming you have some experience with Git, GitHub, and VSCode. You can still follow along if you do not have any experience, but you’ll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/join" rel="noopener noreferrer"&gt;A GitHub account&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; installed in your machine.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt; installed in your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;VS Code has a Git integration as one of its source control options, but for it to work, &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt; needs to be installed on your machine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Integrating Github with VS Code is done through &lt;a href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github" rel="noopener noreferrer"&gt;Github Pull Requests and Issues&lt;/a&gt; extension. &lt;br&gt;
Open VS Code and click on the extensions panel. Search for GitHub Pull Requests and Issues. Next, install the extension and authenticate with GitHub.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605878892147_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605878892147_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After installing the extension, click on the account icon on the activity bar to log in to your GitHub account.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605880295225_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605880295225_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the “Sign in to use GitHub Pull Request and Issues link.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881020275_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881020275_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VS Code will navigate you to the browser. Click on the  &lt;strong&gt;Continue&lt;/strong&gt;  button to give VS Code access to GitHub.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881508014_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881508014_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see a screen asking if you want to authorize GitHub for VS Code. Click the Authorize GitHub button. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881754006_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605881754006_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Confirm your GitHub password to continue. You will see a success screen with your authorization token as displayed below. &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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606742691049_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606742691049_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are not redirected to VS Code, copy the token manually and switch back to VS Code. Click on “Signing in to github.com” in the Git status bar at the bottom of the screen, paste the token and press the Enter or return key on your keyboard. You may need to reload your VS Code window for the extension to start working.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605930727685_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605930727685_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone a project
&lt;/h2&gt;

&lt;p&gt;We will clone by clicking on the &lt;strong&gt;Clone Repository&lt;/strong&gt;  button in the source control view. Click on the “Clone from GitHub” link as seen below.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605932725325_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605932725325_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see a dropdown asking if you want to enable authentication through GitHub. Click the &lt;strong&gt;Allow&lt;/strong&gt; button. VS Code may redirect you to your browser, where you need to authorize GitHub for VS Code like we did when setting up; otherwise, you should see a dropdown with a list of the repositories you have on your GitHub account. You can search for and clone any repository on GitHub.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605943824556_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605943824556_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select where you want the repository to be stored. If you already have a folder, select it and click the &lt;strong&gt;Select Repository Location&lt;/strong&gt; button. You can also open your desired folder on VS Code and then clone into it.&lt;/p&gt;

&lt;p&gt;Once it finishes, you will see a prompt on VS Code asking if you want to open your cloned file in the current window or a new window. &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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605944675582_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605944675582_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to clone a repository belonging to someone else, you can click on the &lt;strong&gt;Clone Repository&lt;/strong&gt; button in the source control view. Paste the URL of the repository in the search bar.&lt;/p&gt;

&lt;p&gt;See the example below.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606815924751_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606815924751_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage and commit
&lt;/h2&gt;

&lt;p&gt;While working or making changes to files, your source control tab should reflect the number of files you have made changes. &lt;br&gt;
Click on the source control tab to see a list of all the files you’ve made changes to. Click on any file or hover over it until you see a plus sign appear. Click on the plus sign, and VS Code will add the file to your staging environment.  &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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606391433345_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606391433345_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have many files and want to stage all of them, instead of clicking the plus sign one after the other, you can click on the &lt;strong&gt;More Actions menu (...).&lt;/strong&gt; From the dropdown, select &lt;strong&gt;Changes&lt;/strong&gt; and select &lt;strong&gt;Stage All Changes.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606392016142_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606392016142_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To commit the staged files, add your commit message and click the checkmark. This will save your changes to your local repository.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606392212484_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606392212484_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new branch
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click the current branch name from the git status bar.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605956492013_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1605956492013_image.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select “Create new branch” from the dropdown - this will create a branch from the current branch you are working on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type in the name of the new branch and hit Enter. VS Code will automatically switch to the new branch.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create a branch from an already existing branch
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606368403647_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606368403647_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the dropdown, select “Create new branch from…” - This will create a new branch from some other branch in the current git repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stash Changes
&lt;/h2&gt;

&lt;p&gt;If you are working on something and do not want to commit the changes yet, probably because you haven’t finished working on them, you need to stash them. Stashing them will move your modified files into a stack of unfinished changes and leave you with a clean working directory. You can restore the stashed files at any time, even on a different branch.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the source control tab.&lt;/li&gt;
&lt;li&gt;Click on the More Actions menu (...) on the changes view.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606383563682_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606383563682_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select Stash from the dropdown.&lt;/li&gt;
&lt;li&gt;Select Stash again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;VS Code will prompt you to enter a stash message to identify the stash and hit the Enter key. You will have a clean working directory now. &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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606384242083_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606384242083_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To restore stashed changes, click on the &lt;strong&gt;More Actions menu (...)&lt;/strong&gt;, hover over &lt;strong&gt;Stash&lt;/strong&gt; and select &lt;strong&gt;Apply Stash.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606384791864_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606384791864_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see a dropdown of your stashed changes. In the screenshot above, we have just one. Go ahead and select the stash you want to apply. This will apply the changes and still leave the entry in the stash.&lt;br&gt;
If you want to restore the stashed changes and delete the entry from the list of stashes, instead of selecting &lt;strong&gt;Apply Stash,&lt;/strong&gt; select &lt;strong&gt;Pop Stash&lt;/strong&gt; from the dropdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Push changes
&lt;/h2&gt;

&lt;p&gt;To push changes in your local repository to a remote repository on GitHub that you own or are a contributor to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the source control tab&lt;/li&gt;
&lt;li&gt;Click on the More Actions menu &lt;strong&gt;(...)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Push, Pull.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Push to…&lt;/strong&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606394558581_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606394558581_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be given an option of any configured remote repository.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606394891819_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606394891819_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the repository, and that’s it. If you want to check if the changes were pushed to GitHub, you can go to the GitHub repository and confirm.&lt;/p&gt;

&lt;h2&gt;
  
  
  View commit timeline
&lt;/h2&gt;

&lt;p&gt;You can view the Git commit history of every file in the timeline view. The timeline view will, by default, update to show the timeline for whatever file you currently have open.  &lt;/p&gt;

&lt;p&gt;To view the timeline for a specific file in your project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the file.&lt;/li&gt;
&lt;li&gt;Scroll down to the bottom of the File Explorer and click on Timeline.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606623624550_image.png"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For every commit in the Timeline, you’ll see the commit title, the name of the person who made the commit, and when that commit was made.&lt;br&gt;
If you click on any commit, it’ll show you a diff view of the changes made by that commit.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606623967432_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606623967432_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create pull requests
&lt;/h2&gt;

&lt;p&gt;To create a pull request after the changes in the local repository has been pushed to the remote repository on GitHub, you’ll need to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the GitHub Pull Request tab to open the Pull Requests view.&lt;/li&gt;
&lt;li&gt;Click on the + button.&lt;/li&gt;
&lt;li&gt;Choose the target branch for the pull request and hit the  Enter key.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606665480672_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606665480672_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your branch hasn’t been published yet, the extension will do it for you. After completing the first three steps above, VS Code will prompt you to pick a name for the branch and hit the Enter key.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606665917171_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606665917171_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After publishing the branch, you’ll need to select a title for the pull request. From the menu, as seen in the screenshot below, you can use the latest commit message, the branch name, or specify a custom title.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606671319548_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606671319548_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you select the pull request title, your pull request will be created. &lt;br&gt;
You can add a code reviewer and label if you want.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606711594261_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606711594261_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull from a remote repository
&lt;/h2&gt;

&lt;p&gt;To pull from a remote branch into your local repository, you need to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the source control tab.&lt;/li&gt;
&lt;li&gt;Click on the More Actions menu &lt;strong&gt;(...).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Pull, Push.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Pull&lt;/strong&gt; if you have  *&lt;strong&gt;*only one remote connected or **Pull from&lt;/strong&gt; if you have multiple remotes to pick from.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714379690_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714379690_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you select &lt;strong&gt;Pull from&lt;/strong&gt;, you’ll need to select the remote you want to pull from. As seen below, I have only my default remote, which is origin.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714552152_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714552152_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll also need to select a branch to pull from.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714877062_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606714877062_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you select your branch, that’s it!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a remote repository
&lt;/h2&gt;

&lt;p&gt;To add a remote repository to your project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the source control menu.&lt;/li&gt;
&lt;li&gt;Click on the More Actions menu &lt;strong&gt;(...).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Remote&lt;/strong&gt; and click on &lt;strong&gt;Add Remote…&lt;/strong&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724116850_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724116850_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either provide the repository URL or add a remote from GitHub.&lt;br&gt;
Click on Add remote from GitHub. You can search for a repository name or select one from the dropdown as seen below.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724314487_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724314487_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you’ll have to provide a remote name you can reference easily and press  Enter.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724776182_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606724776182_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add remote from URL, you can paste the repository URL in the search bar and follow the same steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish a new project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open your project on VS Code.&lt;/li&gt;
&lt;li&gt;Click on the source control menu.&lt;/li&gt;
&lt;li&gt;Click on Publish to GitHub button - This option is only available if git has not been initialized in the project.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll have to decide if you want to make it a public or private repository&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720160712_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720160712_image.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the file you want to include in the first commit and click the &lt;strong&gt;Ok&lt;/strong&gt;   button.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720383582_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720383582_image.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I created just the &lt;code&gt;index.html&lt;/code&gt; file for this illustration, as seen below.&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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720839630_image.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%2Fpaper-attachments.dropbox.com%2Fs_DEFC8E4E34C657FCAAEA3AB05A1BBEA0BF3ED9898BE389E85B79000C12D080F9_1606720839630_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository has been successfully published to Github.&lt;/p&gt;

&lt;p&gt;Yayyy!! You made it to the end of this post, and I hope that you found new tips or tricks to enhance your productivity regardless of your experience level. I bet you’d agree with me that this is the coolest thing since Jollof rice. If you haven’t had Jollof rice, we need to fix that!! Thank you for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Continuous Integration for End-To-End Tests with Cypress and GitHub Actions</title>
      <dc:creator>Ifeoma Imoh</dc:creator>
      <pubDate>Tue, 10 Nov 2020 08:32:16 +0000</pubDate>
      <link>https://forem.com/iphiee_oma/continuous-integration-for-end-to-end-tests-with-cypress-and-github-actions-19a5</link>
      <guid>https://forem.com/iphiee_oma/continuous-integration-for-end-to-end-tests-with-cypress-and-github-actions-19a5</guid>
      <description>&lt;p&gt;In this article, we are going to learn how to create a continuous integration process for Cypress tests. Github Actions can automate, customize and execute your software development workflows right in your repository and it also supports software project development in a variety of ways, both in Programming Language and Operating System Stack. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Integration (CI)&lt;/strong&gt;, is a software development practice which requires automating the integration of software changes from multiple contributors into a single software project. Each change is validated by creating a build and running automated tests against the build. Getting fast feedback on the impact and outcome of changes lead to better collaboration and software quality. &lt;/p&gt;

&lt;p&gt;This article will cover the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to create your first GitHub Actions to run Cypress tests on a hosted website.&lt;/li&gt;
&lt;li&gt;Schedule GitHub Actions Jobs to run at a given interval.&lt;/li&gt;
&lt;li&gt;How to setup GitHub Actions to run Cypress tests for a local project.&lt;/li&gt;
&lt;li&gt;Send test results to Cypress dashboard for monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cypress team has open sourced an action to make running Cypress end-to-end on GitHub easy. Let’s get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;The only required prerequisites is that you should have some experience writing Cypress tests. No prior GitHub Actions experience is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up GitHub Actions to Run Cypress Tests on a Hosted Website
&lt;/h2&gt;

&lt;p&gt;A workflow is a configurable automated process made up of one or multiple Jobs (Jobs will be explained further down this post). Workflow files must be stored in &lt;code&gt;.github/workflow&lt;/code&gt; directory of your repository and they are defined using YAML syntax (&lt;code&gt;.yml&lt;/code&gt; or &lt;code&gt;.yaml&lt;/code&gt; file extension). If you are new to YAML and want to learn more, I would recommend this &lt;a href="https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes" rel="noopener noreferrer"&gt;Learn YMAL in five minutes&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cypress doesn’t recommend running tests on a deployed website Instead, tests should be part of your code project and should live in the same repository. This way it is more efficient to manage and ship code using CI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, you need to create a &lt;code&gt;.github/workflows&lt;/code&gt; folder with a &lt;code&gt;main.yml&lt;/code&gt; file in the project directory and add these code snippets into the  &lt;code&gt;main.yml&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;name&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt;  This is the name of our workflow. GitHub is going to display this on our repository’s action page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;E2E tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;on&lt;/code&gt;:  This is the event that triggers the workflow. This can be a single event, an array of events or an event configuration map that schedules. In our case here, this triggers the workflow on &lt;code&gt;push&lt;/code&gt; or &lt;code&gt;pull request&lt;/code&gt;  but only for the develop branch. We are also specifying an array of different activity &lt;code&gt;types&lt;/code&gt; for our &lt;code&gt;pull request&lt;/code&gt; event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
      &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;synchronize&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;reopened&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;jobs&lt;/code&gt;: We now know that a workflow can be made up of one job or a collection of jobs. Jobs run at the same time in parallel (default) or sequentially depending on the status of a previous job. Jobs run in their own environments specified by &lt;code&gt;runs-on&lt;/code&gt; and here we are using the latest version of ubuntu. For each job, a virtual machine is spawned and other jobs won’t be able to access it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cypress-run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;steps&lt;/code&gt;: A job is made up of small sub-tasks called steps. In each step, we can run commands, run setup tasks or run an action in our public repository. Not all steps run an action but all actions run as a step.  As seen below, we have three steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
          &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup npm package&lt;/span&gt;
          &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run E2E test&lt;/span&gt;
          &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cypress-io/github-action@v1&lt;/span&gt;
          &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;baseUrl=https://seedxb.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;name&lt;/code&gt;  field is what GitHub displays as the name of the step inside the actions tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;checkout&lt;/code&gt;  action is is going to &lt;code&gt;clone&lt;/code&gt; the repository inside the workspace directory in GitHub action environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The  &lt;code&gt;Setup npm package&lt;/code&gt;  as the name implies will run &lt;code&gt;npm install&lt;/code&gt; on the cloned repository and install all our dependencies and The &lt;code&gt;run&lt;/code&gt; field specifies a Bash command to run for this step.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last step,  &lt;code&gt;Run E2E test&lt;/code&gt;  will use Cypress GitHub actions to run our tests for us. We do not need to explicitly specify the run command for the test.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;With&lt;/code&gt; This field specifies options to configure the action.  Actions are like functions and they can define parameters to influence their behaviours dynamically. Here, our action parameter is defined using &lt;code&gt;with&lt;/code&gt; which is a key/value map. In our case, we are passing a &lt;code&gt;config&lt;/code&gt; parameter using &lt;code&gt;with&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;we can use public actions such as &lt;code&gt;actions/checkout@v1&lt;/code&gt; or run command line programs, as we do here with &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you can push to your repository and you’ll see a new tab under the repository called &lt;strong&gt;Actions,&lt;/strong&gt; click it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604928463220_Screenshot%2B2020-11-09%2Bat%2B5.27.12%2BPM.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604928463220_Screenshot%2B2020-11-09%2Bat%2B5.27.12%2BPM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Schedule GH Actions Jobs to run at a given interval
&lt;/h2&gt;

&lt;p&gt;We can also setup our workflow to run on a schedule using &lt;a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07" rel="noopener noreferrer"&gt;POSIX cron syntax&lt;/a&gt; independent of any activity on the repository. The &lt;code&gt;schedule&lt;/code&gt; event lets us define a schedule for our workflow to run on. As seen below, the scheduled event here gets triggered at 9am daily. GitHub provides detailed documentation on scheduled events &lt;a href="https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# push&lt;/span&gt;
      &lt;span class="c1"&gt;# pull_request&lt;/span&gt;
      &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this is what our code should look like: -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;E2E tests&lt;/span&gt;
    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
      &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;synchronize&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;reopened&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
       &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*/5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cypress-run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
            &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup npm package&lt;/span&gt;
            &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run E2E test&lt;/span&gt;
            &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cypress-io/github-action@v1&lt;/span&gt;
            &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;baseUrl=https://seedxb.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Setup GitHub Actions to Run Cypress Tests for a Local Project (Optional but Recommended)
&lt;/h2&gt;

&lt;p&gt;The workflow is basically the same as seen above the only difference is that we are going to add a  &lt;code&gt;wait-on&lt;/code&gt;  parameter that checks and waits for our local server to be up and running before running tests. By default, &lt;code&gt;wait-on&lt;/code&gt; will retry for 60 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Blog tests&lt;/span&gt;
    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cypress-run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
            &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run blog test&lt;/span&gt;
            &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cypress-io/github-action@v1&lt;/span&gt;
            &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm start&lt;/span&gt;
              &lt;span class="na"&gt;wait-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000'&lt;/span&gt;
              &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;baseUrl=https://localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I’ve stripped off some lines so you can focus on what is important for testing locally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice how we’ve updated the &lt;code&gt;baseUrl&lt;/code&gt;  in the config parameter to point to a localhost endpoint. Ensure that you have an app running at port 3000 which you intend to test.&lt;/p&gt;

&lt;h1&gt;
  
  
  Send test results to Cypress dashboard for monitoring
&lt;/h1&gt;

&lt;p&gt;Cypress dashboard is an option that provides details and visual representation of our test runs, their reports, status, and events that took place during execution. It basically gives you details of what happened when your tests ran.&lt;/p&gt;

&lt;p&gt;The Cypress dashboard service is very useful when you are running test cases in a CI environment. We won’t be covering benefits or features provided by Cypress dashboard service in this article but for more information on that, click &lt;a href="https://docs.cypress.io/guides/dashboard/introduction.html#Organize-projects" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to setup a Cypress dashboard&lt;/strong&gt;&lt;br&gt;
Open the test runner and click on the runs tab of your project. Of course there will be no record of test runs visible because we are yet to set it up. Now click on the &lt;strong&gt;Connect to dashboard&lt;/strong&gt; button.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604823169685_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604823169685_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be prompted to log in to the Cypress dashboard to be able to record your test. To do that, you can log in with your Google or Github account. You should see a success message after a successful login and you will be asked to provide the following details as seen below.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604823766927_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604823766927_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can give your project a name - this can be changed anytime. &lt;/li&gt;
&lt;li&gt;Select who owns the project - You can personally own it or create an organisation. I have taken ownership as seen above.&lt;/li&gt;
&lt;li&gt;Finally, you need to decide if you want to make it a private or public project - as seen above, I have provided a public access to mine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After providing the details, you can click the &lt;strong&gt;Set up project&lt;/strong&gt; button. You should see a view explaining how to record your first run.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604828168431_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604828168431_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that your key MUST be confidential and private to you. I left mine for demo purpose and has deactivated it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Recording Test Runs To your Dashboard&lt;/strong&gt;&lt;br&gt;
Firstly, Cypress will, by default, auto-populate your cypress.json  file with a unique project ID as seen above. You can check your cypress.json file to verify this.&lt;/p&gt;

&lt;p&gt;Secondly, we won’t be running the above mentioned command in the terminal, we are going to set the record key as an environmental variable in the project’s repository on Github.  Click on the &lt;strong&gt;Settings&lt;/strong&gt; button.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604835350959_Screenshot%2B2020-11-08%2Bat%2B3.33.19%2BPM.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604835350959_Screenshot%2B2020-11-08%2Bat%2B3.33.19%2BPM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;Secrets&lt;/strong&gt; tab on the left hand menu to navigate to the Secrets page then click on &lt;strong&gt;New secret&lt;/strong&gt; button on the right hand side of the screen.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604835794258_Screenshot%2B2020-11-08%2Bat%2B3.42.26%2BPM.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604835794258_Screenshot%2B2020-11-08%2Bat%2B3.42.26%2BPM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see a screen as shown below. Type in the name of your secret then copy the value of your record key from the runs tab of your test runner and paste it in the value field then click the &lt;strong&gt;Add secret&lt;/strong&gt; button.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604836646101_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604836646101_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update your workflow configuration to include a &lt;code&gt;record&lt;/code&gt; field and a &lt;code&gt;CYPRESS_RECORD_KEY&lt;/code&gt; env variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;     &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# - name: Checkout&lt;/span&gt;
        &lt;span class="c1"&gt;# - name: Setup npm package&lt;/span&gt;
       &lt;span class="c1"&gt;# - name: Run E2E test&lt;/span&gt;
        &lt;span class="c1"&gt;#  uses: cypress-io/github-action@v1&lt;/span&gt;
          &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm start&lt;/span&gt;
             &lt;span class="na"&gt;wait-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000'&lt;/span&gt;
             &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;baseUrl=http://localhost:3000&lt;/span&gt;
            &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;record&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;CYPRESS_RECORD_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CYPRESS_RECORD_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;record&lt;/code&gt;: This tells Cypress to  take video recording, screenshots and logs of all our test runs. &lt;br&gt;
We are also passing our dashboard record key as an environment variable here. Cypress action by default runs the &lt;code&gt;cypress run&lt;/code&gt; command for us. In addition to that if it sees a &lt;code&gt;CYPRESS_RECORD_KEY&lt;/code&gt; and a &lt;code&gt;record&lt;/code&gt; property set to &lt;code&gt;true&lt;/code&gt;,  it will automatically start recording the test.&lt;/p&gt;

&lt;p&gt;Now we are all set!! Push to GitHub and as soon as the tests finish running,  you should be able to see the details of the tests on the dashboard via the Runs tab of the test runner.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604849383867_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604849383867_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on any record, it’s run will open in chrome. You’ll see a detailed record of test runs, number of test cases that passed or failed, videos, screenshots (for failed test cases),  operating system on which the tests ran, duration, etc as shown below.&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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604905149137_image.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%2Fpaper-attachments.dropbox.com%2Fs_6B9EC876947FA629B19A9354DDC63067B9600D58036E526233F5449438141FA8_1604905149137_image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yayyyyy!!! We finally have our dashboard up and running. If you made it to this point, CONGRATULATION!!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cicd</category>
      <category>githubactions</category>
    </item>
  </channel>
</rss>
