<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Asim</title>
    <description>The latest articles on DEV Community by Asim (@asim_ansari7).</description>
    <link>https://dev.to/asim_ansari7</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%2F175714%2F03618946-c04b-4eaa-979d-f1237494b005.jpg</url>
      <title>DEV Community: Asim</title>
      <link>https://dev.to/asim_ansari7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asim_ansari7"/>
    <language>en</language>
    <item>
      <title>Setting up a personal blog with Gatsby and Contentful CMS</title>
      <dc:creator>Asim</dc:creator>
      <pubDate>Sat, 13 Feb 2021 17:03:50 +0000</pubDate>
      <link>https://dev.to/asim_ansari7/setting-up-a-personal-blog-with-gatsby-and-contentful-cms-10c8</link>
      <guid>https://dev.to/asim_ansari7/setting-up-a-personal-blog-with-gatsby-and-contentful-cms-10c8</guid>
      <description>&lt;h2&gt;
  
  
  Scope:
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will learn how to set up Gatsby with Contentful CMS and then deploy the application on Netlify for free. &lt;/p&gt;

&lt;h2&gt;
  
  
  Background:
&lt;/h2&gt;

&lt;p&gt;Prior to this, I had my blog site running on AWS(&lt;a href="https://dev.to/asim_ansari7/deploy-a-react-node-app-to-production-on-aws-2gdf"&gt;deployment post&lt;/a&gt;) that required extra effort to set up, and publishing content on it was a bit tedious. Moreover, I had a free tier plan that got expired, and the relevant services(&lt;strong&gt;EC2 t2.micro&lt;/strong&gt; &amp;amp; &lt;strong&gt;RDS db.t2.micro&lt;/strong&gt;) were being billed at around a dollar a day. &lt;br&gt;
I wanted to revamp my blog site and improve the content management flow in particular so started looking out for other options and got to know about  &lt;strong&gt;Static Site Generators&lt;/strong&gt; and was amazed at how incredibly easy it was to work with them. I chose &lt;strong&gt;Gatsby&lt;/strong&gt; to build the front-end layer of the blog and integrated it with &lt;strong&gt;Contentful CMS&lt;/strong&gt; to fetch data from there.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up Gatsby:
&lt;/h2&gt;

&lt;p&gt;Install Gatsby CLI globally on your machine by running the following command from the terminal.&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;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="nx"&gt;gatsby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To generate a new project run:&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;gatsby&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new project folder with all of the starter files. Switch to the project directory and run &lt;br&gt;
gatsby develop&lt;br&gt;
This would start the gatsby server on the default port of 8000. &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%2Fimages.ctfassets.net%2F8pwqq37w808a%2F1nQcp2pXVP3L4Gz7dlsGMA%2F5e951ef7df4a96329c84c3e4b313ca54%2FGatsby-default.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%2Fimages.ctfassets.net%2F8pwqq37w808a%2F1nQcp2pXVP3L4Gz7dlsGMA%2F5e951ef7df4a96329c84c3e4b313ca54%2FGatsby-default.png" title="Gatsby-Default-Page" alt="Gatsby-Default-Page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Gatsby Starter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.com/starters/?" rel="noopener noreferrer"&gt;Starters&lt;/a&gt; are basically boilerplate code that is maintained by the community to facilitate the development process. We can add another argument to our project setup command that is the URL of the starter that we want to use.&lt;/p&gt;

&lt;p&gt;I initialized my project by using this &lt;a href="https://www.gatsbyjs.org/starters/W3Layouts/gatsby-starter-delog/" rel="noopener noreferrer"&gt;starter&lt;/a&gt; and running the following command:&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;gatsby&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;gatsby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//github.com/W3Layouts/gatsby-starter-delog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found the markup, styling, and dark mode feature super cool so went with it to speed things up. I did some customizations and changed the CMS to Contentful which was more powerful. The final site can be found &lt;a href="https://404found.tech/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Contentful CMS
&lt;/h2&gt;

&lt;p&gt;A CMS is pretty useful as it offers a nice interface for managing content and exposes APIs to pull data from it. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;contentful.com&lt;/a&gt;  and create a free account. &lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;space&lt;/strong&gt; for your project content from the sidebar menu.&lt;/li&gt;
&lt;li&gt;Next head to the &lt;strong&gt;Content model&lt;/strong&gt; tab, which could be thought of as schema for your actual content or blog posts. It will have fields like the blog title, description, publishing date, etc. &lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Content model&lt;/strong&gt; tab to add a content type and click on the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;relevant fields&lt;/strong&gt; in your model by clicking on the &lt;strong&gt;Add Field&lt;/strong&gt; button. I had added the following fields:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2F8pwqq37w808a%2F2mNEyQoteFrLzTQg1bIkkG%2F25ba561a4e1b5cf1ce46864a3315116e%2FContenful-Model.png" title="Content-Model" alt="Content-Model"&gt;
&lt;/li&gt;
&lt;li&gt;Save it and head to the &lt;strong&gt;Content Tab&lt;/strong&gt; to create your first post by clicking on the &lt;strong&gt;Add Blog Post&lt;/strong&gt; button.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2F8pwqq37w808a%2F1fBRUMEIwrkJcgx1Mt8hSH%2F16dd1da94cf802e0086c10d22bca0c51%2FContent-Tab.png" title="Content-Tab" alt="Content-Tab"&gt;
&lt;/li&gt;
&lt;li&gt;Hit the publish button once done and now we can start accessing this data from the Gatsby site.&lt;/li&gt;
&lt;li&gt;Prior to it, go to the &lt;strong&gt;Settings&lt;/strong&gt; dropdown menu and click on the &lt;strong&gt;API Keys&lt;/strong&gt; and generate a new key by clicking on the Add API Key button. Copy the &lt;strong&gt;Space ID&lt;/strong&gt; and &lt;strong&gt;Access Token&lt;/strong&gt; that will be required later.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Gatsby Project Setup:
&lt;/h2&gt;

&lt;p&gt;Project Github link: &lt;a href="https://github.com/Asim1996/gastby-blog" rel="noopener noreferrer"&gt;https://github.com/Asim1996/gastby-blog&lt;/a&gt;&lt;br&gt;
In the installed starter project run the following command to install the Contentful plugin:&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;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;gatsby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;contentful&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source plugin is required for pulling content types, entries, and assets into Gatsby from Contentful spaces. Add the plugin to &lt;strong&gt;gatsby-config.js&lt;/strong&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="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="na"&gt;siteMetadata&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="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;    
&lt;span class="p"&gt;{&lt;/span&gt;      
&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-source-contentful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      
&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;        
&lt;span class="na"&gt;spaceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CONTENTFUL_SPACE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        
&lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CONTENTFUL_ACCESS_TOKEN&lt;/span&gt;      
&lt;span class="p"&gt;},&lt;/span&gt;      
&lt;span class="na"&gt;forceFullSync&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;    
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;strong&gt;.env&lt;/strong&gt; file in your project root directory and paste the &lt;strong&gt;Contentful Space ID&lt;/strong&gt; and &lt;strong&gt;Access Token&lt;/strong&gt; in it.&lt;br&gt;
Modify your development script in the &lt;strong&gt;package.json&lt;/strong&gt; file to fetch data from the &lt;strong&gt;.env&lt;/strong&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;develop&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;env-cmd .env gatsby develop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For fetching all blog posts data the &lt;strong&gt;allContentfulBlogPost&lt;/strong&gt; node would be used in the GraphQL query.&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%2Fimages.ctfassets.net%2F8pwqq37w808a%2F6YN6vRyk0KIRd38L53h7hg%2F81723af829a5df681a8b05b6a80b6a3e%2Fgraphql_query.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%2Fimages.ctfassets.net%2F8pwqq37w808a%2F6YN6vRyk0KIRd38L53h7hg%2F81723af829a5df681a8b05b6a80b6a3e%2Fgraphql_query.png" title="GraphQL-Query" alt="GraphQL-Query"&gt;&lt;/a&gt;&lt;br&gt;
The above query returns the list of all posts available in Contentful which is then passed as props to the Card Component to generate a view for all posts.&lt;br&gt;
Rather than fetching the post &lt;strong&gt;body&lt;/strong&gt; too in the initial index page and passing it as props down the child component, we will be creating dynamic pages with the help of &lt;strong&gt;slug&lt;/strong&gt; content-type defined in our blog schema and adding configurations in the &lt;strong&gt;gatsby-node.js&lt;/strong&gt; file as defined below.&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Create blog pages dynamically&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createPages&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;graphql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/templates/blog.js&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    query {
      allContentfulBlogPost {
        edges {
          node {
            slug
          }
        }
      }
    }
  `&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allContentfulBlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;createPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;blogTemplate&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="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&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="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code dynamically generated blog pages basis the markup defined in the template file and the slug that is being fetched from Contentful in the building process of your Gatsby site.&lt;br&gt;
In your project src directory create a new folder named &lt;strong&gt;templates&lt;/strong&gt; and create a file named blog.js in it.&lt;br&gt;
The following code is used to fetch the relevant blog post basis the &lt;strong&gt;slug&lt;/strong&gt; that comes from the context object from the &lt;strong&gt;gatsby-node.js&lt;/strong&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="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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query($slug: String!) {
    contentfulBlogPost(slug: { eq: $slug }) {
      title
      publishedDate(formatString: "MMMM Do, YYYY")
      description
      backgroundImage{
      title
             fluid(maxWidth: 300, maxHeight:200) { 
             ...GatsbyContentfulFluid       
             }
             file{
        url
        fileName
        contentType
      }
     }
     body{
       json
     }
   }
}
`&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSX in the file can be modified or styled accordingly basis on the data we now have as props.&lt;br&gt;
To render the &lt;strong&gt;Rich Text&lt;/strong&gt; content(blog post body) install the following package:&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;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;contentful&lt;/span&gt;&lt;span class="sr"&gt;/rich-text-react-rendere&lt;/span&gt;&lt;span class="err"&gt;r
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and for syntax highlighting then use the following package:&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;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;syntax&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;highlighter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template file can then be modified to use the above packages and render the content in a more appealing way. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying to Netlify
&lt;/h2&gt;

&lt;p&gt;Push your code on Github(or any other Git provider) and signup for a free account on &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;. Then, click on the &lt;strong&gt;New site from Git button&lt;/strong&gt; and choose your Git provider and the repository that needs to be deployed. Add your Environment Variables by clicking on the &lt;strong&gt;Show advanced&lt;/strong&gt; button on the deploy settings page.&lt;br&gt;
Click on the &lt;strong&gt;Deploy site&lt;/strong&gt; button that will trigger the deployment process and once it is complete you'll see your site URL. And that's it, a few button clicks and your site is live on the internet.&lt;/p&gt;
&lt;h2&gt;
  
  
  Optional Setups:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mapping a custom domain:&lt;/strong&gt; If you have an existing domain bought from any external Domain Name provider (GoDaddy, BigRock, etc). Head to your domain name provider and create an &lt;strong&gt;A record&lt;/strong&gt; and link Netlify’s load balancer IP with your domain name to complete the entire setup.&lt;br&gt;
Helpful links: &lt;a href="https://docs.netlify.com/domains-https/custom-domains/" rel="noopener noreferrer"&gt;Custom Domains&lt;/a&gt;, &lt;a href="https://docs.netlify.com/domains-https/custom-domains/configure-external-dns/" rel="noopener noreferrer"&gt;Configure External DNS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Netlify Forms:&lt;/strong&gt; In your contact form just add the following attributes&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&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;netlify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;netlify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;honeypot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bot-field&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;input&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;hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bot-field&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;input&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;hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form-name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Netlify's bots will automatically detect the attribute &lt;strong&gt;data-netlify="true"&lt;/strong&gt; when you deploy your site and process the form for you. &lt;br&gt;
Head to Settings &amp;gt; Forms &amp;gt; Form notifications and receive an email alert anytime a new submission comes through.&lt;br&gt;
Helpful Link: &lt;a href="https://docs.netlify.com/forms/setup/" rel="noopener noreferrer"&gt;Netlify Forms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring a Netlify build hook:&lt;/strong&gt;  If you make changes to your Contentful post data, you can either trigger a deploy manually from Netlify or generate a Netlify build hook (that you can add to Contentful CMS) to trigger an automatic redeploy of your site. &lt;br&gt;
From the Netlify dashboard, navigate to the "Settings" for your site, choose "Build &amp;amp; deploy", and scroll to "Build hooks". &lt;br&gt;
Click &lt;strong&gt;Add build hook&lt;/strong&gt; that then generates an HTTPS URL that responds to requests by triggering a build and deployment of your site. Copy the URL and navigate back to the Contentful web app. From the Settings choose &lt;strong&gt;Webhooks&lt;/strong&gt; and paste the URL that Netlify provided into the form.&lt;br&gt;
Helpful link : &lt;a href="https://www.contentful.com/developers/docs/tutorials/general/automate-site-builds-with-webhooks/" rel="noopener noreferrer"&gt;Netlify Build Hook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding Disqus to Gatsby:&lt;/strong&gt; Having a comment section in your blog post can be pretty helpful and that could easily be set up signing up on &lt;a href="https://disqus.com/profile/signup/?next=https%3A//disqus.com/" rel="noopener noreferrer"&gt;Disqus&lt;/a&gt;. Post that, install the following package:&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;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;disqus&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;react&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following config in your template 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="p"&gt;...&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disqusConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://404found.tech/&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentfulBlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&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="na"&gt;identifier&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;props&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;contentfulBlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&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="na"&gt;title&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentfulBlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Disqus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DiscussionEmbed&lt;/span&gt; &lt;span class="nx"&gt;shortname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;404found-tech&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disqusConfig&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="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading.&lt;br&gt;
Cheers!!&lt;/p&gt;

</description>
      <category>react</category>
      <category>gatsby</category>
      <category>webdev</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Setting up Social Logins(Google + Microsoft) with Node.js and Passport.js</title>
      <dc:creator>Asim</dc:creator>
      <pubDate>Wed, 07 Oct 2020 20:08:32 +0000</pubDate>
      <link>https://dev.to/asim_ansari7/setting-up-social-logins-with-node-js-and-passport-js-1m16</link>
      <guid>https://dev.to/asim_ansari7/setting-up-social-logins-with-node-js-and-passport-js-1m16</guid>
      <description>&lt;p&gt;Before diving into code, let's first briefly discuss what the heck is &lt;strong&gt;Oauth&lt;/strong&gt;?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What is Oauth:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;OAuth(or Open Authorization)&lt;/strong&gt; is one of the approaches for authenticating a user in an application. It makes it much easier and faster for an end-user to choose a social login(Google, Outlook, or Twitter, etc) to signup on an application rather than the traditional (email/password) signup form.&lt;/p&gt;

&lt;p&gt;Simply, it is a way to provide third-party websites or apps access to user's data(name, email, etc.) without requiring them to share their credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Oauth Abstract View&lt;/strong&gt;
&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%2Fblogs-static-assets.s3.amazonaws.com%2Fnode%2Foauth-basic.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%2Fblogs-static-assets.s3.amazonaws.com%2Fnode%2Foauth-basic.png" alt="oauth basic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lot of things are happening behind the scenes and a detailed explanation is provided in the below image as to how we are going to set this up in our Node app.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Oauth Developer's View&lt;/strong&gt;
&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%2Fblogs-static-assets.s3.amazonaws.com%2Fnode%2Foauth_complex.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%2Fblogs-static-assets.s3.amazonaws.com%2Fnode%2Foauth_complex.png" alt="oauth complex"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now set up the above login flow by first setting up our app on Google and Microsoft Console.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Google - Create client ID and client secret&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Head to &lt;a href="https://console.developers.google.com/" rel="noopener noreferrer"&gt;Google API Console&lt;/a&gt; and sign in using your email id.&lt;/li&gt;
&lt;li&gt; From the project drop-down create a new project by filling in the project name and organization(optional).&lt;/li&gt;
&lt;li&gt; In the sidebar under "APIs &amp;amp; Services", select &lt;strong&gt;OAuth Consent Screen&lt;/strong&gt;, choose the appropriate &lt;strong&gt;User Type&lt;/strong&gt; basis requirement. For public-facing app select external.&lt;/li&gt;
&lt;li&gt; Fill in the application name, logo(optional), support email(optional), and hit Save.&lt;/li&gt;
&lt;li&gt; Switch to &lt;strong&gt;Credentials&lt;/strong&gt; tab from the sidebar and from the Create credentials drop-down list, choose OAuth client ID.&lt;/li&gt;
&lt;li&gt; Under Application type, select Web application.&lt;/li&gt;
&lt;li&gt; In Authorized redirect URI add &lt;a href="http://localhost:5500/auth/google/redirect" rel="noopener noreferrer"&gt;http://localhost:5500/auth/google/redirect&lt;/a&gt; for dev env, for production env, this will be the server IP address or domain name followed by /auth/google/redirect&lt;/li&gt;
&lt;li&gt; Press the Create button and copy the generated &lt;strong&gt;client ID&lt;/strong&gt; and &lt;strong&gt;client secret&lt;/strong&gt;. This will be used later in the Node app&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Microsoft - Create client ID and client secret&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Head to &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Microsoft Azure portal&lt;/a&gt; and sign in using your email id.&lt;/li&gt;
&lt;li&gt; Search for &lt;strong&gt;App registrations&lt;/strong&gt; from the search bar.&lt;/li&gt;
&lt;li&gt; Select &lt;strong&gt;New registration&lt;/strong&gt; from the top and fill in your application name.&lt;/li&gt;
&lt;li&gt; Choose Account type basis your requirement. For our application, it will be &lt;strong&gt;personal accounts + organizational directory&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; In Redirect URI add &lt;a href="http://localhost:5500/auth/microsoft/redirect" rel="noopener noreferrer"&gt;http://localhost:5500/auth/microsoft/redirect&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt; Press the Register button to register your app.&lt;/li&gt;
&lt;li&gt; From the sidebar select &lt;strong&gt;Overview&lt;/strong&gt; tab and copy the Application (client) ID. To generate the client secret head to &lt;strong&gt;Certificates &amp;amp; secrets&lt;/strong&gt; from the sidebar and click on &lt;strong&gt;New Client Secret&lt;/strong&gt; from the Client secrets section. Copy the generated secret for future use.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Passport Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It is an &lt;strong&gt;authentication middleware&lt;/strong&gt; and can be easily configured with express. It provides a comprehensive set of strategies supporting authentication using a username and password, Google, Facebook, Twitter, and many more.&lt;/p&gt;

&lt;p&gt;Install the following packages:&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;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;oauth20&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;microsoft&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Routes Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will be setting up &lt;strong&gt;token-based&lt;/strong&gt; redirection basis social login in our app. This flow is helpful when we have an existing app with email, password setup, and social logins are being added as an enhancement.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;express-generator&lt;/strong&gt; to set up the basic boilerplate for the express app.&lt;/p&gt;

&lt;p&gt;Setup the following routes in index.js:&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;scope&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;profile&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;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;session&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/google/redirect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;session&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;failureRedirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://localhost:3000/login`&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&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;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//req.user has the redirection_url&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Microsoft Routes&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/microsoft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;microsoft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;session&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;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/microsoft/redirect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;microsoft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;session&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;failureRedirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://localhost:3000/login`&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&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;user&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;Over here the route &lt;strong&gt;/auth/google&lt;/strong&gt; or &lt;strong&gt;/auth/microsoft&lt;/strong&gt; is called when the user clicks Log in with Google or Microsoft in the browser. Behind the scenes, passport communicates with Google/Microsoft and directs the user to their respective consent screen.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;consent screen&lt;/strong&gt; tells users who is requesting access to their data and what kind of data the app is asking to access. The latter part of the statement comes under &lt;strong&gt;scope&lt;/strong&gt;. In our app, we need access to the user's Google &lt;strong&gt;profile&lt;/strong&gt; and &lt;strong&gt;email address&lt;/strong&gt;, thus added it to the scope object. Redirect routes will be discussed later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Google and Microsoft Strategies Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a new file(&lt;strong&gt;google_oauth.js&lt;/strong&gt;) in the project root directory and add the following code.&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;passport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport&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;GoogleStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport-google-oauth20&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&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;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleStrategy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;callbackURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:5500/auth/google/redirect`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;//same URI as registered in Google console portal&lt;/span&gt;
  &lt;span class="na"&gt;clientID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//replace with copied value from Google console&lt;/span&gt;
  &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&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;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&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;try&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;user_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//profile object has the user info&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user_email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//check whether user exist in database&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;redirect_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;user&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;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;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;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;//generating token&lt;/span&gt;
        &lt;span class="nx"&gt;redirect_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:3000/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="c1"&gt;//registered on FE for auto-login&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;//redirect_url will get appended to req.user object : passport.js in action&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;redirect_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:3000/user-not-found/`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// fallback page&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redirect_url&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;done&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In a similiar fashion, create a new file(&lt;strong&gt;microsoft_oauth.js&lt;/strong&gt;) and copy paste the above code. Just make the following changes to it:&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;MicrosoftStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport-microsoft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MicrosoftStrategy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
&lt;span class="na"&gt;callbackURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:5500/auth/microsoft/redirect`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="na"&gt;clientID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MICROSOFT_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MICROSOFT_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="na"&gt;scope&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;openid&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;profile&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;email&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A brief explanation of the arguments in the callback function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;accessToken&lt;/strong&gt; are used to make API requests on behalf of a user. Not required in our app.&lt;/li&gt;
&lt;li&gt; Generally, access tokens have a limited lifetime so a &lt;strong&gt;refreshToken&lt;/strong&gt; can be used to obtain new access tokens.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;profile&lt;/strong&gt; will contain user profile information provided by the service provider.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;done&lt;/strong&gt; the callback function which gets invoked upon successful look-up and supplies passport with the user that gets authenticated. The first argument to done is the error object which is null in our code thus telling passport that things are fine and there is no error.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an end-user approves our app in the consent screen, the redirect api's(&lt;strong&gt;/auth/google/redirect&lt;/strong&gt; or &lt;strong&gt;/auth/microsoft/redirect&lt;/strong&gt;) are invoked , &lt;strong&gt;req.user&lt;/strong&gt; object is already set to the appropriate &lt;strong&gt;redirection URL&lt;/strong&gt; through passport and the user lands on a page basis that.&lt;/p&gt;

&lt;p&gt;Since we are not maintaining session through cookies thus an additional &lt;strong&gt;session: false&lt;/strong&gt; key was passed. If we have to set up an app using cookies, then this is not passed. Furthermore, we need to require &lt;strong&gt;cookie-session&lt;/strong&gt; and use passport &lt;strong&gt;serializeUser&lt;/strong&gt; and &lt;strong&gt;deserializeUser&lt;/strong&gt; functions to effectively manage the saved cookie basis google/microsoft unique &lt;strong&gt;profile id&lt;/strong&gt;. Though, it is recommended using the &lt;strong&gt;user id&lt;/strong&gt; present in the database.&lt;br&gt;
Require the above two files in &lt;strong&gt;index.js&lt;/strong&gt; and test the application locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optional: App Verification&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Though it is not mandatory if sensitive scopes are not accessed. For production apps, this should be done irrespective of the scope requested.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Microsoft&lt;/strong&gt;, it is pretty easy to get our app verified, head to the Azure portal, and from the sidebar to the branding section.&lt;/p&gt;

&lt;p&gt;Over here, you can upload the app logo. Add in Terms of Service, Privacy statement link if needed. To verify the publisher domain just upload the &lt;strong&gt;microsoft-identity-association.json&lt;/strong&gt; file in &lt;strong&gt;.well-known&lt;/strong&gt; folder on your website s3 bucket.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Google&lt;/strong&gt;, things are a bit tricky. Though some explanation is provided &lt;a href="https://support.google.com/cloud/answer/6158849?hl=en" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
We can Submit our app for Verification from the &lt;strong&gt;OAuth Consent Screen&lt;/strong&gt;(Google Console Portal) after providing the appropriate Authorized domain, Homepage, Term of Service, and privacy policy links. The process takes around &lt;strong&gt;4-5 days&lt;/strong&gt; if no sensitive scope is being requested. A few rounds of follow-up emails from the google team if needed and that's it.&lt;/p&gt;

&lt;p&gt;Apart from getting verified, the benefit of this is that a user can see our &lt;strong&gt;App logo&lt;/strong&gt; and &lt;strong&gt;App name&lt;/strong&gt; in the consent screen which makes it more professional.&lt;/p&gt;

&lt;p&gt;Thanks for reading and congrats on making it till the end.&lt;/p&gt;

&lt;p&gt;Cheers!!&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>authentication</category>
    </item>
    <item>
      <title>System Design Getting Started</title>
      <dc:creator>Asim</dc:creator>
      <pubDate>Sat, 18 Jul 2020 22:06:11 +0000</pubDate>
      <link>https://dev.to/asim_ansari7/system-design-getting-started-2efd</link>
      <guid>https://dev.to/asim_ansari7/system-design-getting-started-2efd</guid>
      <description>&lt;p&gt;Taking a real world example to cover the basics of designing a distributed system.&lt;/p&gt;

&lt;p&gt;Let's say you got an idea of running a fast-food restaurant.&lt;/p&gt;

&lt;p&gt;You start by finding a perfect market place, hiring staff, and managing other expenses.&lt;/p&gt;

&lt;p&gt;Assuming the business goes well, and the restaurant goes popular in the niche market and you are handling hundreds of orders every day. Now, it's time for you to decide how to scale up the business.&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Time To Scale&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;You got two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Pay your current staff more and ask them to work for more hours. This is known as &lt;b&gt;Vertical Scaling&lt;/b&gt; wherein you are increasing the throughput by using the same resources.&lt;/p&gt; 
&lt;p&gt;You can also look out for optimizing the current process by doing some preprocessing before the actual order, let's say preparing some stuff beforehand in the non-peak hour which maps to the usage of a &lt;b&gt;cronjob&lt;/b&gt; in system design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hire more staff to scale up your business and manage the orders effectively at peak hours. This is termed as &lt;b&gt;Horizontal Scaling&lt;/b&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5WlhgKo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/systemdesign/horizontalvsvertical.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5WlhgKo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/systemdesign/horizontalvsvertical.png" alt="vertical-vs-horizontal-scaling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In real-world scenarios, a balanced or hybrid approach is used as there is always an upper limit to how much you can scale a machine vertically. 
You can even look out to hire some backup chef to make your restaurant/system more resilient.&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Expanding on the Strength&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;As a manager, to make sure your business runs smoothly you brainstorm and divide the current chefs into teams based on their expertise.&lt;/p&gt;
&lt;p&gt;Suppose, Team A can be responsible for handling pizza orders, Team B can be utilized for handling burgers and Team C for Sandwiches, and so on.&lt;/p&gt;

&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K5l10-EU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/systemdesign/microservices.png" alt="microservices"&gt;

&lt;p&gt;In a way, you have divided responsibilities amongst the team, and you can route orders to a team basis their specialty can get to know the status more easily plus moving forward you can scale up a particular team based on business requirements.&lt;/p&gt;
&lt;p&gt;This is the central idea behind &lt;b&gt;microservices&lt;/b&gt; in designing systems. As applications become easier to build and maintain when they are broken down into smaller units which work together. Each unit is continuously developed and maintained to handle the overall product.&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Introducing Distributed Systems&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;At this stage, your shop is doing well, you have divided the chef's basis their specialty and your system is available at all times.&lt;/p&gt; 
&lt;p&gt;Now consider the case when there is a power outage, your staff goes on strike that would mean a loss of business for that day or maybe you want to expand your business even more.&lt;/p&gt;
&lt;p&gt;So you can look out to start another shop in a different location that delivers orders, initially the numbers of chefs may be lesser but at least you have a backup and your business isn't impacted much.
With this approach, you have &lt;b&gt;distributed&lt;/b&gt; your system.&lt;/p&gt;
&lt;p&gt;
A &lt;b&gt;distributed system&lt;/b&gt; is a system with multiple components located on different machines working together and it appears as if a single computer is processing the query to the end-user. These machines work concurrently and can fail independently without affecting the whole system’s uptime.
&lt;/p&gt;

&lt;p&gt;Apart from scaling the other advantages of a distributed system are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Fault Tolerance&lt;/b&gt; is the property that enables a system to continue operating properly in the event of the failure of (or one or more faults within) some of its components.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
&lt;b&gt;Low Latency&lt;/b&gt;: Latency is a networking term to describe the total time it takes a data packet to travel from one node to another. With distributed systems, we can have multiple nodes and routing traffic to hit the node that is closest to it thus reducing the latency.
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this, the level of complexity has increased in the system, as it would now get a bit difficult to maintain and handle requests across the system.&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Handling orders effectively&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;Now when a customer places an order through a phone call, the responsibility to route his order to a particular shop is on you basis his location and the order processing time of each shop.&lt;/p&gt; 

&lt;p&gt;Balance the load and making sure not every request is sent to one single shop/server is done by a &lt;b&gt;load balancer&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;b&gt;load balancer&lt;/b&gt; acts as the “traffic cop” sitting in front of the servers and routing client requests across all servers in a manner that maximizes speed and capacity utilization. If a single server goes down, the load balancer redirects traffic to the remaining online servers. When a new server is added to the server group, the load balancer automatically starts to send requests to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ERcjM9gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/systemdesign/load-balancer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ERcjM9gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/systemdesign/load-balancer.png" alt="load-balancer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Tracking metrics&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;You can maintain a track of every event that's happening in each shop, such as order processing times, most ordered food items, most delivered location, etc basically the success metric to analyze and leverage it for future use.&lt;/p&gt;

&lt;p&gt;Similarly, track for failure too like whenever there is a fault in a machine or deliver agent not showing up early which can hamper your response time if not handled well.&lt;/p&gt;

&lt;p&gt;Apart from these, a system should be &lt;b&gt;extensible&lt;/b&gt; meaning you can easily build something totally new on top of it. Maybe start a bakery shop and take orders for that too. &lt;/p&gt;

&lt;p&gt;The above used approach when designing a system is termed as &lt;b&gt;High-Level System Design&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;I hope through the above example you got some basic info related to system design.&lt;/p&gt;

</description>
      <category>design</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hoisting in JavaScript</title>
      <dc:creator>Asim</dc:creator>
      <pubDate>Wed, 27 May 2020 14:14:44 +0000</pubDate>
      <link>https://dev.to/asim_ansari7/hoisting-in-javascript-34k6</link>
      <guid>https://dev.to/asim_ansari7/hoisting-in-javascript-34k6</guid>
      <description>&lt;p&gt;Demystifying one of the quirks of the language.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article is originally posted &lt;a href="https://404found.tech/blog/hoisting-in-javascript"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider the following code sample&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;var&lt;/span&gt; &lt;span class="nx"&gt;myName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bruce Wayne&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getCity&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;  
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="s2"&gt;Gotham&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nx"&gt;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;myName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="nx"&gt;getCity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing the code will return Bruce Wayne and Gotham which was kinda expected.&lt;/p&gt;

&lt;p&gt;To make things interesting, try running 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="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;myName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="nx"&gt;getCity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bruce Wayne&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getCity&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;  
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="s2"&gt;Gotham&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In most programming languages this would throw an error as code is executed line by line. But with Javascript that's not the case, upon execution, the output will be Gotham and undefined.&lt;/p&gt;

&lt;p&gt;And you are introduced to one of the many quirks in the language. This phenomenon is known as &lt;strong&gt;hoisting&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you look up for the term &lt;strong&gt;Hoisting&lt;/strong&gt; online, in many places it is explained as if the variables and functions in JS are moved to the top by the JavaScript Engine&lt;/p&gt;

&lt;p&gt;To gain a bit more understanding and why this happens we need to dive into the &lt;strong&gt;Execution Context&lt;/strong&gt; and how it is created.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What is an Execution Context?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Execution context (EC) is defined as the environment in which the JavaScript code is executed. It contains properties that you haven't even declared in your code. If you run the above code in the browser and open the console window, you get access to the &lt;strong&gt;window&lt;/strong&gt; object as well as the &lt;strong&gt;this&lt;/strong&gt; keyword. These were added by the &lt;strong&gt;JS Engine&lt;/strong&gt; and for the &lt;strong&gt;Global Execution Context&lt;/strong&gt; which is the default execution context they are the same thing. Similarly, we have a &lt;strong&gt;Functional execution context&lt;/strong&gt; which is created by the JS engine whenever it finds any function call. Each function has its own execution context. In layman terms, global is something which is not inside any function, so in the code above, the variable &lt;strong&gt;myName&lt;/strong&gt; and function &lt;strong&gt;getCity&lt;/strong&gt; get attached to the global scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Execution Context in Detail&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An execution context is created in two-phase by the interpreter.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Creation Phase&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7Hrmg0SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/javascript/creation_phase.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Hrmg0SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/javascript/creation_phase.png" alt="creation phase" width="747" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Global object is created only when we are dealing with the Global Execution Context, the &lt;strong&gt;this&lt;/strong&gt; keyword is always created in an execution context. In this phase, the parser identifies the variables and the functions created in code and sets up memory space for it which is confusingly called &lt;strong&gt;hoisting&lt;/strong&gt; . So when the code is run line by line it can actually access them. However, things work differently for variables and functions. A function is entirely placed in memory with all the code inside of it, while all variables are set to &lt;strong&gt;undefined&lt;/strong&gt; in the first phase.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Execution Phase&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This phase is pretty simple, in this phase code is run line by line, interpreting it and executing it on the computer.&lt;/p&gt;

&lt;p&gt;Consider the following code sample:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getCity&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;  
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="s2"&gt;Gotham&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nx"&gt;getCity&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;myName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bruce Wayne&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;myName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Upon execution, we get Gotham, undefined, and Bruce Wayne. And this would now be clear as to when we log myName before it's initialization it is actually set to &lt;strong&gt;undefined&lt;/strong&gt; in the creation phase.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope, you got a grasp about how the JavaScript interpreter is evaluating your code and you could avoid possible unexpected behavior in the future. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>DEPLOY A REACT + NODE APP TO PRODUCTION ON AWS</title>
      <dc:creator>Asim</dc:creator>
      <pubDate>Sat, 23 May 2020 20:07:08 +0000</pubDate>
      <link>https://dev.to/asim_ansari7/deploy-a-react-node-app-to-production-on-aws-2gdf</link>
      <guid>https://dev.to/asim_ansari7/deploy-a-react-node-app-to-production-on-aws-2gdf</guid>
      <description>&lt;p&gt;A detailed walkthrough on setting up a production-ready web server from scratch on the Amazon EC2 service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article is originally posted &lt;a href="https://404found.tech/blog/deploy-react-node-app-on-aws"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Scope:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We will setup a &lt;strong&gt;full-stack(Node, Express, React)&lt;/strong&gt; app with MySQL database. We will deploy the app to an AWS EC2 instance running &lt;strong&gt;Ubuntu Server 16.04 LTS&lt;/strong&gt;. The setup uses &lt;strong&gt;NGINX&lt;/strong&gt; as a &lt;strong&gt;reverse proxy&lt;/strong&gt; and also to serve react static files, &lt;strong&gt;PM2&lt;/strong&gt; is used as a cluster manager. The MySQL database will be deployed to &lt;strong&gt;AWS RDS&lt;/strong&gt;, &lt;strong&gt;phymyadmin&lt;/strong&gt; will be setup too and connected to the rds to handle queries through GUI. And finally we will map the EC2 instance to a domain name.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Background&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the past, I had used &lt;strong&gt;Heroku&lt;/strong&gt; for deploying node apps and &lt;strong&gt;Netlify&lt;/strong&gt; for static web apps which provides with &lt;strong&gt;ready-to-use environments&lt;/strong&gt; making the deployment process much faster and easier by hiding away all the complexities. However, setting up an AWS instance gives much more insights of what goes under the hood in making your website public.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Setup:&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting up VPC:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Virtual Private Cloud&lt;/strong&gt; is basically a virtual location that contains our AWS services(example: web servers, databases, elastic cache, file servers, and messaging services).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Go to Amazon VPC Dashboard by using the following link &lt;a href="https://console.aws.amazon.com/vpc"&gt;https://console.aws.amazon.com/vpc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on "Create VPC" button. The page looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--USlNKeLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/create-vpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--USlNKeLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/create-vpc.png" alt="vpc dashboard" width="880" height="312"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The VPC has been named as &lt;strong&gt;react-node vpc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CIDR&lt;/strong&gt;, is an alternative to traditional subnetting which is used to specify the number of significant bits that make up the routing or networking portion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CIDR Notation(10.10.0.0/16)&lt;/strong&gt; indicates that the first two octet is for networking and the remaining 2 octet to define host.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on create VPC button to finish the VPC setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Subnet setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A subnet or &lt;strong&gt;sub network&lt;/strong&gt; is a way to divide the resources in the VPC. The web server(EC2) needs to be accessible by the internet while the RDS should only be accessed internally thus public and a private subnet is needed for security.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Creating a Public Subnet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CpYZyBHk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/public-subnet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CpYZyBHk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/public-subnet.png" alt="public subnet" width="880" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This subnet can have any address between 10.10.1.0 - 10.10.1.255.  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating a Private Subnet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Axo1_5lV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/private-subnet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Axo1_5lV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/private-subnet.png" alt="private subnet" width="880" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This subnet can have any address between 10.10.2.0 - 10.10.2.255. Also, an availability zone is required to make this subnet work with our database. Moreover, deploying a database to AWS requires 2 subnets in different availability zones, so setup a second one with the same flow.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Security Groups setup
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;security group&lt;/strong&gt; acts as a virtual firewall for the instance to control inbound and outbound traffic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click on the security groups tab and click on create security group. Add a name ,description and attach the VPC which was created before. The page looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kE6PBAzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kE6PBAzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/sg.png" alt="security group" width="880" height="264"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After creating the security groups edit the &lt;strong&gt;Inbound Rules&lt;/strong&gt; as shown.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TriUfUbe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/inbound-rule.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TriUfUbe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/inbound-rule.png" alt="inbound rules" width="880" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSH&lt;/strong&gt; is used to log in to the EC2 instance from a personal computer. Update your personal IP address in the source section every time unless a &lt;strong&gt;static IP&lt;/strong&gt; is available.&lt;br&gt;
Port 80 and port 443 allows normal traffic over the internet.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Creating a new Ubuntu Server on AWS EC2&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Go to the EC2 Service section and click the launch instance button&lt;/li&gt;
&lt;li&gt; Select the "Ubuntu Server 16.04 LTS" Amazon Machine Image (AMI).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the instance details as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G_oxynEp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/ec2-instance.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G_oxynEp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/ec2-instance.png" alt="ec2 instance" width="880" height="456"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the VPC which was created and add the public subnet. Storage and tags can be left as default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign the existing security group to the instance which was created in previous steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Review and Launch to spin up the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It will prompt to &lt;strong&gt;Create a new key pair&lt;/strong&gt;. Enter a name and click "Download Key Pair" to download the private key, this will be used to connect to the server via SSH.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISVWLmHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/key-pair.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISVWLmHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/key-pair.png" alt="ec2 instance" width="880" height="454"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Post successful creation, navigate to the instance page and right-click on the newly created instance. Click on connect which opens a pop-up detailing the steps to connect via SSH.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NHXPwAI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/key-pair-connection.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NHXPwAI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/key-pair-connection.png" alt="key-pair-connection" width="880" height="554"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;RDS Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Head towards the RDS database dashboard.&lt;/li&gt;
&lt;li&gt; Before creating a database, a &lt;strong&gt;subnet group&lt;/strong&gt; will be created to communicate with the server. It will expand over two availability zones to protect the database against server failure.&lt;/li&gt;
&lt;li&gt; Click on the subnet group tag and then click on create DB subnet group.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a Name and Description and select the VPC which was created. Then, attach the private subnets for that VPC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--usF9PyZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/sbnet-group.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--usF9PyZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/sbnet-group.png" alt="subnet-group" width="880" height="733"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now we are ready to create our database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1abhYpGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1abhYpGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/db.png" alt="database creation" width="824" height="752"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the next page, set the VPC and the subnet group that was created. Remember the &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;password&lt;/strong&gt; that you set here, this will be used to connect to the SQL server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The advanced setting can be done as shown below:&lt;/p&gt;


&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U_Ib9zG9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/configure-db.png" alt="database configuration" width="839" height="742"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Create database&lt;/strong&gt; button to finish the setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;While the database is being created, head to the VPC dashboard and create a new security-group following the same steps as above and set the inbound rule as shown below:  &lt;/p&gt;


&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onuOY7Vo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/db-sg.png" alt="database security group configuration" width="880" height="233"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, attach this security group to the database by clicking the modify button and selecting the security group under Networking and Security section.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To check everything is working correctly, ssh into your instance by opening a new terminal, and connecting the same way as shown above.&lt;/p&gt;

&lt;p&gt;Install &lt;strong&gt;MySQL&lt;/strong&gt; with the following command:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sudo apt-get install mysql-server mysql-client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During installation, setup will ask you to enter MySQL root account and password to connect to the &lt;strong&gt;local&lt;/strong&gt; database.&lt;/p&gt;

&lt;p&gt;After successful installation, connect to the &lt;strong&gt;host database&lt;/strong&gt; by typing the command&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mysql -u username -p -h hostname&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Input the password that you used while setting up the rds. &lt;strong&gt;Hostname(Endpoint)&lt;/strong&gt; can be found from RDS dashboard page under &lt;strong&gt;Connectivity &amp;amp; security&lt;/strong&gt; tab in database summary page.&lt;/p&gt;

&lt;p&gt;If things go well you will see a screen like this after a successful connection from the terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZicNgVxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/mysql-connected.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZicNgVxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/mysql-connected.png" alt="mysql connected" width="555" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;React and Node Project Setup:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Project Github link: &lt;a href="https://github.com/Asim1996/blog"&gt;https://github.com/Asim1996/blog&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deploying the project to AWS EC2 instance.&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SSH into your instance first using &lt;br&gt;
&lt;strong&gt;ssh i- “keypair.pem” ubuntu@public-ip-address&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install git using the command:&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="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; 
&lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Clone your project into the server with the command:
&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;sudo&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After cloning the project we can see all the files as shown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YFwIOAgg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/project.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YFwIOAgg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/project.png" alt="project" width="449" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing &lt;strong&gt;node&lt;/strong&gt; and &lt;strong&gt;npm&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will install &lt;strong&gt;nvm(node version manager)&lt;/strong&gt; first using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo curl https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, install node using&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nvm install node-version&lt;/strong&gt; I had used (v8.16.0)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post-installation we can head into our server directory and install all packages using &lt;strong&gt;npm install&lt;/strong&gt;, but first, we need to give write permissions to that folder using:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo chmod 777 path-to-directory&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;path-to-directory in this project was (/home/ubuntu/blog/server)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the client side of our application we will be using yarn.Set it up as follows:
&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;curl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sS&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - &lt;/span&gt;
&lt;span class="nx"&gt;echo&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deb https://dl.yarnpkg.com/debian/ stable main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;tee&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yarn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt; 
&lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;apt&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; 
&lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;apt&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;recommends&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this switch to the client directory and run &lt;strong&gt;yarn add&lt;/strong&gt; to install all dependencies after setting the required permission as done previously.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Run the command &lt;strong&gt;yarn run build&lt;/strong&gt; to get the build folder which will be served by Nginx in the next step.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Configure NGINX to serve the Node.js API and React front-end&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since our application is made up of two separate projects that both need to be accessed via the same port (HTTP on port 80), we're going to use NGINX as our public-facing web server to receive requests for both the front-end and back-end, and decide where to send each request based on its path. Requests beginning with the path &lt;strong&gt;/api/&lt;/strong&gt;* will be proxied through to the Node.js API running on port 5000, while other requests will serve the React front-end app and associated files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Installing Nginx by typing the following command in terminal:&lt;br&gt;
&lt;br&gt;
&lt;code&gt;sudo apt-get install -y nginx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To check if it's running, access: &lt;strong&gt;&lt;a href="http://ec2-public-ip/"&gt;http://ec2-public-ip/&lt;/a&gt;&lt;/strong&gt;. If it shows ‘Welcome to nginx!’ this means that nginx is running and we can proceed to the next step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, head to the following directory&lt;br&gt;
&lt;br&gt;
&lt;code&gt;cd /etc/nginx/sites-available/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delete the default file and create a new one with the following code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rcoobsn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/nginx-config.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rcoobsn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/nginx-config.png" alt="nginx-config" width="614" height="355"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the file and restart nginx using&lt;br&gt;
&lt;br&gt;
&lt;code&gt;sudo systemctl restart nginx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;NGINX Config guide:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;server { ... }&lt;/strong&gt; defines a server block that contains the configuration for a virtual server within NGINX.&lt;/li&gt;
&lt;li&gt;  Through &lt;strong&gt;location / { ... }&lt;/strong&gt; we define a block that contains the configuration for requests that have a URI beginning with a forward slash (/), in it we set the react build as the root route. Then we set the index.html file as the main index, and on every subsequent request we serve the same index.html file.&lt;/li&gt;
&lt;li&gt;  The &lt;strong&gt;location /api { ... }&lt;/strong&gt; defines a location block to serve requests that have a URI beginning with /api which will be proxied to our Node server using the property  &lt;strong&gt;proxy_pass &lt;a href="http://localhost:5000"&gt;http://localhost:5000&lt;/a&gt;;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optional: Setting up phpmyadmin&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It will make our life easier by accessing the database using a secure web interface instead of using the terminal for DB commands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; First install PHP using the command:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo apt install php-fpm php-mysql&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Then Install phpMyAdmin using: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo apt-get install phpmyadmin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;During the installation, It will ask you which web server you would like the software to automatically configure. Since we are Nginx which isn’t one of the available options, you can just hit TAB, and then ENTER to bypass this prompt. The next prompt will ask if you would like dbconfig-common to configure a database for phpMyAdmin to use. Select “Yes” to continue. Enter the database administrator password that was configured during the MySQL installation to allow these changes. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After installation, for the Nginx webserver to find and serve the phpMyAdmin files correctly, we’ll need to create a &lt;strong&gt;symbolic link&lt;/strong&gt; from the installation files to our Nginx document root directory: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo ln -s /usr/share/phpmyadmin /var/www/html&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; phpMyAdmin relies on &lt;strong&gt;mcrypt&lt;/strong&gt; PHP module so this need to be enabled too&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo phpenmod mcrypt&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl restart php7.0-fpm&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Setting up an authentication prompt before visiting /phpmyadmin route in the browser.
We’ll create a password file that will store the authentication credentials. Nginx requires that passwords be encrypted using the crypt() function.
To create an encrypted password, type: &lt;code&gt;openssl passwd&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It prompts to enter a password and then will return an encrypted version of it, copy that as we will be using it while setting authentication file&lt;/p&gt;

&lt;p&gt;Navigate to &lt;strong&gt;/etc/nginx/&lt;/strong&gt; and create a new file &lt;strong&gt;pma_pass&lt;/strong&gt; with the following content&lt;/p&gt;

&lt;p&gt;&lt;code&gt;username_of_your_choice:copied_encrypted_version_password&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save and close the file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;After this, update the default file under the nginx folder as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bvGUtu4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/phpmyadminsetup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bvGUtu4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/phpmyadminsetup.png" alt="nginx-final-config" width="618" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Restart nginx using &lt;strong&gt;sudo systemctl restart nginx&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adding our RDS server in phpMyAdmin&lt;/p&gt;

&lt;p&gt;Navigate to:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sudo nano /etc/phpmyadmin/config.inc.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Find the following lines in config.inc.php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="cm"&gt;/*  
    * End of servers configuration  
    */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Append the following lines above the "End of servers configuration" line:&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;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Servers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;host&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxxx.xxxxxxxxxx.us-east-1.rds.amazonaws.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Servers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;port&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3306&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Servers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connect_type&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tcp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Servers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;extension&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mysql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Servers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compress&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="nx"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Save the file and exit.&lt;br&gt;
Head to browser and type (&lt;a href="http://ec2-public-ip/phpmyadmin/"&gt;http://ec2-public-ip/phpmyadmin/&lt;/a&gt;) which results in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iF-T6XCz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/php-myadmin-browser.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iF-T6XCz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blogs-static-assets.s3.amazonaws.com/aws/php-myadmin-browser.png" alt="php-myadmin-browser" width="880" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional: PM2 setup
&lt;/h3&gt;

&lt;p&gt;PM2 is a cluster manager and allows us to run our app automatically and also restart it automatically if it crashes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Install pm2 using:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npm install pm2 -g&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; To start pm2 navigate to the server directory and type:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;pm2 start app.js -i 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PM2 figures out how many instances to create on its own using the above command.&lt;/p&gt;

&lt;p&gt;Below are some useful pm2 commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;pm2 list:&lt;/strong&gt; list all the running processes&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;pm2 restart app 0:&lt;/strong&gt; restart app with id 0&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;pm2 delete app 0:&lt;/strong&gt; delete app with id 0&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;pm2 logs&lt;/strong&gt; Display all processes logs in streaming&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;pm2 stop all&lt;/strong&gt; Stop all processes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;And Finally, Test our new application running on AWS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Enter the &lt;strong&gt;hostname&lt;/strong&gt;(ec2 instance public IP) in the browser to view your application live on the web.&lt;/p&gt;

&lt;p&gt;Additionally, you can buy a domain name from any Domain Name provider (GoDaddy, BigRock, etc) and link it by using an &lt;strong&gt;Elastic IP&lt;/strong&gt; which is preserved even if we stop and start our instance in a virtual private cloud.&lt;/p&gt;

&lt;p&gt;To do this&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Allocate an Elastic IP address from Amazon’s pool of public IPv4 addresses.&lt;/li&gt;
&lt;li&gt;  Associate the Elastic IP address with the running instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Head to your domain name provider and create an &lt;strong&gt;A record&lt;/strong&gt; and link the Elastic IP with your domain name to complete the entire setup.&lt;/p&gt;

&lt;p&gt;and phew! that's it! Thanks for reading and congrats on making it till the end. I hope this makes your deployment lifecycle easier as a newbie.&lt;/p&gt;

&lt;p&gt;Cheers!!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>react</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
