<?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: ITNEXT</title>
    <description>The latest articles on DEV Community by ITNEXT (@itnext).</description>
    <link>https://dev.to/itnext</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F524%2F90433eeb-676f-472a-885e-59d54cb1f097.png</url>
      <title>DEV Community: ITNEXT</title>
      <link>https://dev.to/itnext</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itnext"/>
    <language>en</language>
    <item>
      <title>Deploy on AWS using React, Flask, and SQLite.</title>
      <dc:creator>Tallan Groberg</dc:creator>
      <pubDate>Sun, 30 Jul 2023 20:22:35 +0000</pubDate>
      <link>https://dev.to/itnext/using-sqlite-flask-and-react-to-deploy-on-aws-d31</link>
      <guid>https://dev.to/itnext/using-sqlite-flask-and-react-to-deploy-on-aws-d31</guid>
      <description>&lt;p&gt;Deploying to AWS can be difficult to learn. I hope to make this easy. &lt;/p&gt;

&lt;p&gt;Credits: Professor Andrew Awdeorio&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will get out of this
&lt;/h2&gt;

&lt;p&gt;You will have a very simple web app live on the internet. Click &lt;a href="http://ec2-3-136-156-17.us-east-2.compute.amazonaws.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="http://ec2-3-136-156-17.us-east-2.compute.amazonaws.com/root" rel="noopener noreferrer"&gt;here&lt;/a&gt; to see the end result. &lt;/p&gt;

&lt;h2&gt;
  
  
  Possible limitations
&lt;/h2&gt;

&lt;p&gt;To ensure you don't waste your time. SQLite might not be the best option if the application that you hope to make with this is very data intensive. &lt;/p&gt;

&lt;p&gt;While this article is set up for image upload functionality to be possible. This is not covered in this tutorial. You can store references to images very easily with the functionality I use in this tutorial. Checking out my tutorial  on &lt;a href="https://dev.to/itnext/how-to-do-image-upload-with-firebase-in-react-cpj"&gt;image uploads with firebase&lt;/a&gt; is a great option until I release a tutorial about that for this stack. &lt;/p&gt;

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

&lt;p&gt;This tutorial does not go over best practices for securing your AWS account upon account creation. If you plan on building applications that hold sensitive user data hosted through AWS and not just this tutorial, I recommend learning about how to &lt;a href="https://aws.amazon.com/iam/resources/best-practices/" rel="noopener noreferrer"&gt;secure your AWS account&lt;/a&gt; before you start building them. &lt;/p&gt;

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

&lt;p&gt;Part 1: creating the database&lt;br&gt;
Part 2: creating a flask app&lt;br&gt;
part 3: Creating the react app&lt;br&gt;
part 4: Setting up an AWS account&lt;br&gt;
part 5: Deploying to AWS&lt;/p&gt;

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

&lt;p&gt;In this tutorial we are going to walk through how to make a deployment to AWS with a simple SQLite server. How to make a flask app capable of interacting with that server to store and retrieve data. And how to make a react app hosted through flask. &lt;/p&gt;

&lt;p&gt;The application itself will be simple but you will able host powerful web applications after completing this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is useful
&lt;/h2&gt;

&lt;p&gt;Completing this tutorial is a great way introduction to hosting on aws. Even if this isn't your typical stack this will show the concepts to make your next deploy easier. &lt;/p&gt;

&lt;p&gt;It's a perfect introduction to scripting. I use commandline scripting in almost every type of project that I do becuase it helps me save so much time in my workflows. &lt;/p&gt;

&lt;p&gt;This can also be used to integrate python apps into something that can be shared on the web. This is important for anyone who has a great python app but doesn't have a means of share that with the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will need.
&lt;/h2&gt;

&lt;p&gt;A text editor. I will be using VS code. &lt;br&gt;
a command line interface. I will be using macOS with unix and zsh. I believe that the type of command line wont matter as long as you understand the corrisponding command for your operating system or look them up as needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/python-version-on-mac-update/" rel="noopener noreferrer"&gt;python3 installed&lt;/a&gt; on your host machine 3.10 or greater.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;github account&lt;/a&gt; we will be using a repo to move all of our code base to an &lt;a href="https://aws.amazon.com/marketplace/pp/prodview-iftkyuwv2sjxi" rel="noopener noreferrer"&gt;ubuntu&lt;/a&gt; instance on AWS since this is currently on the free tier. &lt;/p&gt;

&lt;h2&gt;
  
  
  prerequisite skills.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Basic understanding of python.&lt;/li&gt;
&lt;li&gt;basic knowledge of flask.&lt;/li&gt;
&lt;li&gt;Basic understanding of react. &lt;/li&gt;
&lt;li&gt;good understanding of unix command line.

&lt;ul&gt;
&lt;li&gt;we will use shell scripting in order to test things. if you understand bash this should be straightforward. We will also use many linux commands and I believe I have done a great job of making this as beginner friendly as possible. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;basic understanding of git. &lt;/li&gt;
&lt;li&gt;basic understanding of emacs is a plus but not necessary.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;While I have done many hours of due diligence on this article. Mistakes may still be in here. If you notice anything that isn't right, I am very open to constructive criticism and feedback. I'm also very willing to help anyone who is having trouble to complete this tutorial. I want to see you succeed in deploying a web-app if you are willing to give me your time to learn this and I take not wasting your time very seriously.  &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Making the database.
&lt;/h2&gt;

&lt;p&gt;We are going to start by making a simple project directory. &lt;/p&gt;

&lt;p&gt;Go to the directory where you want this project in the terminal and paste this code snippet. &lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;webapp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;webapp


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

&lt;/div&gt;

&lt;p&gt;next we have to install SQLite via &lt;a href="https://brew.sh/" rel="noopener noreferrer"&gt;homebrew&lt;/a&gt; if on macOS.  &lt;/p&gt;

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

brew &lt;span class="nb"&gt;install &lt;/span&gt;sqlite3


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

&lt;/div&gt;

&lt;p&gt;you can make sure you have the right version by running this line in the terminal. &lt;/p&gt;

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

sqlite3 &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;output: &lt;br&gt;
-- Loading resources from /Users/tallan/.sqliterc&lt;br&gt;
3.32.3 2020-06-18 14:16:19 02c34......&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next we are making a very simple database with one table so that we can test if the database works properly.&lt;/p&gt;

&lt;p&gt;To do this, we want to make a folder to keep 2 files. A small amount of dummy data and a schema. &lt;/p&gt;

&lt;p&gt;from the terminal inside the project directory, we make a new folder /sql&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;sql &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;sql


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

&lt;/div&gt;

&lt;p&gt;From the terminal, now inside the /sql directory, we make 2 files to host each of these. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;data.sql &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;schema.sql


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

&lt;/div&gt;

&lt;p&gt;now we make a folder for stock images. &lt;/p&gt;

&lt;p&gt;I wont provide the images but I took screen shots from an AI photo generator and added them to the following folder and named them after the [fake people(&lt;a href="https://this-person-does-not-exist.com/en" rel="noopener noreferrer"&gt;https://this-person-does-not-exist.com/en&lt;/a&gt;) that I'm about to add to the database. &lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;uploads


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

&lt;/div&gt;

&lt;p&gt;when you run this command you should have all the same filenames. &lt;/p&gt;

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

tree uploads


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

uploads
├── alicewilliams.png
├── bobjohnson.jpeg
├── charliebrown.jpg
├── janesmith.jpg
└── johndoe.png


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

&lt;/div&gt;

&lt;p&gt;Let's add the simple table to the &lt;strong&gt;schema.sql&lt;/strong&gt; file. &lt;/p&gt;

&lt;p&gt;Even though we don't have any foreign keys, this will be good to remember in case we decide to do anything else with the database after the tutorial. &lt;/p&gt;

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

&lt;span class="n"&gt;PRAGMA&lt;/span&gt; &lt;span class="n"&gt;foreign_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;fullname&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;picture&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="nb"&gt;DATETIME&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Add some simple entries to the &lt;strong&gt;data.sql&lt;/strong&gt; file&lt;/p&gt;

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

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'john_doe@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'johndoe.png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Jane Smith'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'jane_smith@yahoo.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'janesmith.jpg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Bob Johnson'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bob_johnson@outlook.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bobjohnson.jpeg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice Williams'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'alice_williams@hotmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'alicewilliams.png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Charlie Brown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'charlie_brown@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'charliebrown.jpg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We move on to the bash scripting portion so that we can make setting up, taking down and reseting the database easy. &lt;/p&gt;

&lt;p&gt;make sure you move your terminal to the project directory.&lt;br&gt;
&lt;em&gt;from inside the sql folder&lt;/em&gt;&lt;/p&gt;

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

tree &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;*output:&lt;/p&gt;

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

├── data.sql
├── schema.sql
└── uploads
    ├── alicewilliams.png
    ├── bobjohnson.jpeg
    ├── charliebrown.jpg
    ├── janesmith.jpg
    └── johndoe.png


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

&lt;/div&gt;

&lt;p&gt;Move back to the projects root directory. &lt;/p&gt;

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

&lt;span class="nb"&gt;cd&lt;/span&gt; ..


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

&lt;/div&gt;

&lt;p&gt;Make a new folder for your bash script and the bash script file while staying in this project directory. &lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;bin &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;bin/db


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

&lt;/div&gt;

&lt;p&gt;I'm going to add these in parts with an explanation of code and will post the whole file at the end. &lt;/p&gt;

&lt;p&gt;at the very top of the &lt;strong&gt;db&lt;/strong&gt; file paste this line.&lt;/p&gt;

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

#!/bin/bash


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

&lt;/div&gt;

&lt;p&gt;this lets the computer know that this is a bash script, so when you run the file, it will be like running many terminal commands as once. &lt;/p&gt;

&lt;p&gt;below that line we will add commands to &lt;a href="https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/" rel="noopener noreferrer"&gt;echo the outputs&lt;/a&gt; so that it's easy to spot errors in these commands. &lt;/p&gt;

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

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-Eeuo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;let's add a friendly usage message for when we don't add an argument. &lt;/p&gt;

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

usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; (create|destroy|reset|dump)"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;usage
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The first block is a function making it so that if we run &lt;code&gt;./bin/db&lt;/code&gt; in the terminal, then there is text that is output to the terminal. &lt;/p&gt;

&lt;p&gt;The second block is saying if the number of terminal arguments used to call this script are not equal to 1 then call the usage function and exit 1. notice that the call to the script from the terminal (&lt;code&gt;./bin/db&lt;/code&gt;) is not considered an argument. &lt;/p&gt;

&lt;p&gt;We have to run this line to enable permissions for &lt;strong&gt;db&lt;/strong&gt; to access the command line. &lt;/p&gt;

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

&lt;span class="nb"&gt;chmod&lt;/span&gt; +x bin/db


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

&lt;/div&gt;

&lt;p&gt;Now you can run this script with this command.&lt;/p&gt;

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

./bin/db


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

&lt;/div&gt;

&lt;p&gt;if you don't run &lt;code&gt;chmod +x bin/db&lt;/code&gt; before you call this script, you will get this error. &lt;/p&gt;

&lt;p&gt;output:&lt;br&gt;
&lt;em&gt;bash: ./bin/db: Permission denied&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you run it after entering &lt;code&gt;chmod +x bin/db&lt;/code&gt; into the terminal then you will get the following output. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;output:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;+ '[' 0 -ne 1 ']'&lt;/em&gt;&lt;br&gt;
&lt;em&gt;+ usage&lt;/em&gt;&lt;br&gt;
&lt;em&gt;+ echo 'Usage: ./bin/db (create|destroy|reset|dump)'&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Usage: ./bin/db (create|destroy|reset|dump)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;+ exit 1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we get to the commands themselves. &lt;/p&gt;

&lt;p&gt;To create a database, we make an else if statement that will run a block of commands based on the argument given when we call the script. &lt;/p&gt;

&lt;p&gt;This command will be &lt;code&gt;./bin/db create&lt;/code&gt; and the code that will run when we call this will be. &lt;/p&gt;

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

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"create"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; var/uploads
    sqlite3 var/App.sqlite3 &amp;lt; sql/schema.sql
    sqlite3 var/App.sqlite3 &amp;lt; sql/data.sql
    &lt;span class="nb"&gt;cp &lt;/span&gt;sql/uploads/&lt;span class="k"&gt;*&lt;/span&gt; var/uploads/
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then in the terminal run. &lt;/p&gt;

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

./bin/db create


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

&lt;/div&gt;

&lt;p&gt;if everything was coded correctly, and you ran &lt;code&gt;chmod +x bin/db&lt;/code&gt; and then &lt;code&gt;./bin/db create&lt;/code&gt; you should have a new folder var and a file called &lt;strong&gt;App.sqlite3&lt;/strong&gt; inside that folder. &lt;/p&gt;

&lt;p&gt;To check, run this command in the terminal&lt;/p&gt;

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

tree var


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

var
├── App.sqlite3
└── uploads
    ├── alicewilliams.png
    ├── bobjohnson.jpeg
    ├── charliebrown.jpg
    ├── janesmith.jpg
    └── johndoe.png


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

&lt;/div&gt;

&lt;p&gt;We want to make a command for each functionality stated by the usage message. &lt;/p&gt;

&lt;p&gt;To do that we will add &lt;code&gt;elif&lt;/code&gt;'s before the closing &lt;code&gt;fi&lt;/code&gt; and after the command for create. &lt;/p&gt;

&lt;p&gt;the rest of the &lt;code&gt;elif&lt;/code&gt; statement will look like this. &lt;/p&gt;

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

elif [ "$1" = "destroy" ]; then
    rm -rf var/App.sqlite3 var/
elif [ "$1" = "reset" ]; then
    ./bin/db destroy
    ./bin/db create
elif [ "$1" = "dump" ]; then
    sqlite3 var/App.sqlite3 .dump


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

&lt;/div&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full &lt;strong&gt;db&lt;/strong&gt; file will look like this. &lt;/p&gt;

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

&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Eeuo&lt;/span&gt; &lt;span class="n"&gt;pipefail&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="nf"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s"&gt;"Usage: $0 (create|destroy|reset|dump)"&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="err"&gt;$#&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ne&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
  &lt;span class="n"&gt;usage&lt;/span&gt;
  &lt;span class="n"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"$1"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;uploads&lt;/span&gt;
    &lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;
    &lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;
    &lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;uploads&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;uploads&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;elif&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"$1"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"destroy"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
&lt;span class="n"&gt;elif&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"$1"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"reset"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="n"&gt;destroy&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;
&lt;span class="n"&gt;elif&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"$1"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dump"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dump&lt;/span&gt;
&lt;span class="n"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Make sure that when you run the following terminal commands that you get the same outputs before moving onto the flask portion. You will be using these commands often.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;From the project directory with no database created&lt;/em&gt;&lt;/p&gt;

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

./bin/db create


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

+ '[' 1 -ne 1 ']'
+ '[' create = create ']'
+ mkdir -p var
+ sqlite3 var/App.sqlite3
+ sqlite3 var/App.sqlite3


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

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

./bin/db destroy


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

+ '[' 1 -ne 1 ']'
+ '[' destroy = create ']'
+ '[' destroy = destroy ']'
+ rm -rf var


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

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

./bin/db reset


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

+ &lt;span class="s1"&gt;'['&lt;/span&gt; 1 &lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; reset &lt;span class="o"&gt;=&lt;/span&gt; create &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; reset &lt;span class="o"&gt;=&lt;/span&gt; destroy &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; reset &lt;span class="o"&gt;=&lt;/span&gt; reset &lt;span class="s1"&gt;']'&lt;/span&gt;
+ ./bin/db destroy
+ &lt;span class="s1"&gt;'['&lt;/span&gt; 1 &lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; destroy &lt;span class="o"&gt;=&lt;/span&gt; create &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; destroy &lt;span class="o"&gt;=&lt;/span&gt; destroy &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; var
+ ./bin/db create
+ &lt;span class="s1"&gt;'['&lt;/span&gt; 1 &lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; create &lt;span class="o"&gt;=&lt;/span&gt; create &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; var/uploads
+ sqlite3 var/App.sqlite3
+ sqlite3 var/App.sqlite3
+ &lt;span class="nb"&gt;cp &lt;/span&gt;sql/uploads/alicewilliams.png sql/uploads/bobjohnson.jpeg sql/uploads/charliebrown.jpg sql/uploads/janesmith.jpg sql/uploads/johndoe.png var/uploads/


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

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

./bin/db dump


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

+ &lt;span class="s1"&gt;'['&lt;/span&gt; 1 &lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; dump &lt;span class="o"&gt;=&lt;/span&gt; create &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; dump &lt;span class="o"&gt;=&lt;/span&gt; destroy &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; dump &lt;span class="o"&gt;=&lt;/span&gt; reset &lt;span class="s1"&gt;']'&lt;/span&gt;
+ &lt;span class="s1"&gt;'['&lt;/span&gt; dump &lt;span class="o"&gt;=&lt;/span&gt; dump &lt;span class="s1"&gt;']'&lt;/span&gt;
+ sqlite3 var/App.sqlite3 .dump
&lt;span class="nt"&gt;--&lt;/span&gt; Loading resources from /Users/tallan/.sqliterc
PRAGMA &lt;span class="nv"&gt;foreign_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON&lt;span class="p"&gt;;&lt;/span&gt;
BEGIN TRANSACTION&lt;span class="p"&gt;;&lt;/span&gt;
CREATE TABLE developer &lt;span class="o"&gt;(&lt;/span&gt;
    fullname TEXT CHECK&lt;span class="o"&gt;(&lt;/span&gt;length&lt;span class="o"&gt;(&lt;/span&gt;fullname&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; 40&lt;span class="o"&gt;)&lt;/span&gt;,
    email TEXT CHECK&lt;span class="o"&gt;(&lt;/span&gt;length&lt;span class="o"&gt;(&lt;/span&gt;email&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; 40&lt;span class="o"&gt;)&lt;/span&gt;,
    picture TEXT CHECK&lt;span class="o"&gt;(&lt;/span&gt;length&lt;span class="o"&gt;(&lt;/span&gt;picture&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; 64&lt;span class="o"&gt;)&lt;/span&gt;,
    password TEXT CHECK&lt;span class="o"&gt;(&lt;/span&gt;length&lt;span class="o"&gt;(&lt;/span&gt;password&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; 256&lt;span class="o"&gt;)&lt;/span&gt;,
    created DATETIME DEFAULT CURRENT_TIMESTAMP
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
INSERT INTO developer VALUES&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;,&lt;span class="s1"&gt;'john_doe@gmail.com'&lt;/span&gt;,&lt;span class="s1"&gt;'johndoe.png'&lt;/span&gt;,&lt;span class="s1"&gt;'password'&lt;/span&gt;,&lt;span class="s1"&gt;'2023-07-23 22:43:59'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
INSERT INTO developer VALUES&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Jane Smith'&lt;/span&gt;,&lt;span class="s1"&gt;'jane_smith@yahoo.com'&lt;/span&gt;,&lt;span class="s1"&gt;'janesmith.jpg'&lt;/span&gt;,&lt;span class="s1"&gt;'password'&lt;/span&gt;,&lt;span class="s1"&gt;'2023-07-23 22:43:59'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
INSERT INTO developer VALUES&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Bob Johnson'&lt;/span&gt;,&lt;span class="s1"&gt;'bob_johnson@outlook.com'&lt;/span&gt;,&lt;span class="s1"&gt;'bobjohnson.jpeg'&lt;/span&gt;,&lt;span class="s1"&gt;'password'&lt;/span&gt;,&lt;span class="s1"&gt;'2023-07-23 22:43:59'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
INSERT INTO developer VALUES&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice Williams'&lt;/span&gt;,&lt;span class="s1"&gt;'alice_williams@hotmail.com'&lt;/span&gt;,&lt;span class="s1"&gt;'alicewilliams.png'&lt;/span&gt;,&lt;span class="s1"&gt;'password'&lt;/span&gt;,&lt;span class="s1"&gt;'2023-07-23 22:43:59'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
INSERT INTO developer VALUES&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Charlie Brown'&lt;/span&gt;,&lt;span class="s1"&gt;'charlie_brown@gmail.com'&lt;/span&gt;,&lt;span class="s1"&gt;'charliebrown.jpg'&lt;/span&gt;,&lt;span class="s1"&gt;'password'&lt;/span&gt;,&lt;span class="s1"&gt;'2023-07-23 22:43:59'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
COMMIT&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Making the flask App.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Ensure part 1 works properly before continuing to part 2.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;We are going to want to make a custom python environment that is specific to this directory&lt;/p&gt;

&lt;p&gt;This will mean we need to define a requirements.txt that's used for defining all the packages.&lt;/p&gt;

&lt;p&gt;If you mess up at any point in trying to do this section run this command in the project directory and it will remove the python env folder that we are about to create. &lt;/p&gt;

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

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To ensure that we have python3 on your machine, run this command. &lt;/p&gt;

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

python3 &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
&lt;em&gt;Python 3.11.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may have a different version but, as long as this is 3.10 or greater you don't have to update to succeed in this tutorial.&lt;/p&gt;

&lt;p&gt;This also assumes that you are not using a python version from Anaconda. &lt;/p&gt;

&lt;p&gt;Another gotcha is that when we run this command it should be a blank output.&lt;/p&gt;

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

&lt;span class="nb"&gt;printenv &lt;/span&gt;PYTHONPATH


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

&lt;/div&gt;

&lt;p&gt;if you do have an output when you run this, you can run this command, but you will have to do so everytime you restart the terminal. &lt;/p&gt;

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

&lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="nt"&gt;--unset&lt;/span&gt; PYTHONPATH


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

&lt;/div&gt;

&lt;p&gt;If all the above checks passed, we can run this command.&lt;/p&gt;

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

 python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This will have created a python environment local to this directory and this command will need to be ran every time we restart the terminal regardless of whether you had an ouput on the command before the one above. If we don't then the flask App will fail to start.&lt;/p&gt;

&lt;p&gt;To activate the environment we run this command. &lt;/p&gt;

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

&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate


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

&lt;/div&gt;

&lt;p&gt;There should be something that says (env) to the left most side of our textbar where we write to the terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8bp2ir209jxjsfqgsqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8bp2ir209jxjsfqgsqy.png" alt="Image description"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;To double check, run this command and it should output the env directory first.&lt;/p&gt;

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

 which &lt;span class="nt"&gt;-a&lt;/span&gt; python


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

&lt;/div&gt;

&lt;p&gt;output:&lt;/p&gt;

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

/Users/tallan/Desktop/article-writing/tutorials/flask-app/project/env/bin/python
/usr/local/bin/python
/usr/bin/python


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

&lt;/div&gt;

&lt;p&gt;Now we want to install &lt;a href="https://jinja.palletsprojects.com/en/3.1.x/" rel="noopener noreferrer"&gt;jinja2&lt;/a&gt; since this is what will allow us to mount the DOM to the flask App with react. It can also be very useful for making simple webpages like forms that are used in addition to react since they can be more responsive and easier to make than full react components, when the page is a simple form or needs little to no database calls, I prefer to use it. &lt;/p&gt;

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

./env/bin/pip &lt;span class="nb"&gt;install &lt;/span&gt;jinja2


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

&lt;/div&gt;

&lt;p&gt;We want to add additional packages to our starter files. To do this we will use a requirements.txt file. &lt;/p&gt;

&lt;p&gt;from the terminal make a requirements.txt file&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;requirements.txt


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

&lt;/div&gt;

&lt;p&gt;copy and paste the following code snippet into the file.&lt;br&gt;
&lt;em&gt;__requirements.txt&lt;/em&gt;_&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;arrow==&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;astroid==&lt;/span&gt;&lt;span class="mf"&gt;2.15&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;attrs==&lt;/span&gt;&lt;span class="mf"&gt;22.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;beautifulsoup&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;4.11&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;bs&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;certifi==&lt;/span&gt;&lt;span class="mf"&gt;2022.12&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;charset-normalizer==&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;click==&lt;/span&gt;&lt;span class="mf"&gt;8.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;dill==&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;exceptiongroup==&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Flask==&lt;/span&gt;&lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;html&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="err"&gt;validator==&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;idna==&lt;/span&gt;&lt;span class="mf"&gt;3.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;iniconfig==&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;isort==&lt;/span&gt;&lt;span class="mf"&gt;5.12&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;itsdangerous==&lt;/span&gt;&lt;span class="mf"&gt;2.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Jinja&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;3.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;lazy-object-proxy==&lt;/span&gt;&lt;span class="mf"&gt;1.9&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;MarkupSafe==&lt;/span&gt;&lt;span class="mf"&gt;2.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;mccabe==&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;packaging==&lt;/span&gt;&lt;span class="mf"&gt;23.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;platformdirs==&lt;/span&gt;&lt;span class="mf"&gt;2.6&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;pluggy==&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;pycodestyle==&lt;/span&gt;&lt;span class="mf"&gt;2.10&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;pydocstyle==&lt;/span&gt;&lt;span class="mf"&gt;6.3&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;pylint==&lt;/span&gt;&lt;span class="mf"&gt;2.16&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;pytest==&lt;/span&gt;&lt;span class="mf"&gt;7.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;python-dateutil==&lt;/span&gt;&lt;span class="mf"&gt;2.8&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;PyYAML==&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;requests==&lt;/span&gt;&lt;span class="mf"&gt;2.28&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;six==&lt;/span&gt;&lt;span class="mf"&gt;1.16&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;snowballstemmer==&lt;/span&gt;&lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;soupsieve==&lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;.post&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;tomli==&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;tomlkit==&lt;/span&gt;&lt;span class="mf"&gt;0.11&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;typing_extensions==&lt;/span&gt;&lt;span class="mf"&gt;4.4&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;urllib&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;1.26&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Werkzeug==&lt;/span&gt;&lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;wrapt==&lt;/span&gt;&lt;span class="mf"&gt;1.14&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;When you run the following command, this will install all the packages in the requirements.txt file to the virtual environment.&lt;/p&gt;

&lt;p&gt;with our env activated and the txt file with all the pages above copied. Let's run the following command. &lt;/p&gt;

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt


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

&lt;/div&gt;

&lt;p&gt;We may get some depreciation warnings, that shouldn't be an issue. &lt;/p&gt;

&lt;p&gt;Run the env activate command again. &lt;/p&gt;

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

&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate


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

&lt;/div&gt;

&lt;p&gt;We are ready to make the flask App itself. &lt;/p&gt;

&lt;p&gt;Lowercase app is a reserved word in flask and I didn't want to call this package tutorial and so I settled for uppercase App. be mindful that there is a distinction between the 2. &lt;/p&gt;

&lt;p&gt;We are going to house most of the App in a folder of the same name.&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;App


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

&lt;/div&gt;

&lt;p&gt;we need an __init__.py file to initialize the package. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/__init__.py


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

&lt;/div&gt;

&lt;p&gt;__init__.py&lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;App package initializer.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;

&lt;span class="c1"&gt;# app is a single object used by all the code modules in this package
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# pylint: disable=invalid-name
&lt;/span&gt;
&lt;span class="c1"&gt;# Read settings from config module (insta485/config.py)
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;App.config&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Overlay settings read from a Python file whose path is set in the environment
# variable INSTA485_SETTINGS. Setting this environment variable is optional.
# Docs: http://flask.pocoo.org/docs/latest/config/
#
# EXAMPLE:
# $ export APP_SETTINGS=secret_key_config.py
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_envvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APP_SETTINGS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;silent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Tell our App about views and model.  This is dangerously close to a
# circular import, but Flask was designed that way.
# (Reference http://flask.pocoo.org/docs/patterns/packages/)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App.views&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App.model&lt;/span&gt;  


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

&lt;/div&gt;

&lt;p&gt;Next we make a &lt;strong&gt;config.py&lt;/strong&gt; file for environment variables specific to the flask app. &lt;/p&gt;

&lt;p&gt;Inside the App directory make a file called config.py&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/config.py


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;config.py&lt;/em&gt;&lt;/p&gt;

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

"""App development configuration."""

import pathlib

# Root of this application, useful if it doesn't occupy an entire domain
APPLICATION_ROOT = '/'

# Secret key for encrypting cookies
SECRET_KEY = b'FIXME SET WITH: $ python3 -c "import os; print(os.urandom(24))"'
SESSION_COOKIE_NAME = 'login'

# File Upload to var/uploads/
APP_ROOT = pathlib.Path(__file__).resolve().parent.parent
UPLOAD_FOLDER = APP_ROOT/'var'/'uploads'
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
MAX_CONTENT_LENGTH = 16 * 1024 * 1024

# Database file is var/App.sqlite3
DATABASE_FILENAME = APP_ROOT/'var'/'App.sqlite3'


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

&lt;/div&gt;

&lt;p&gt;As the TODO suggests, run the following command and replace the &lt;code&gt;SECRET_KEY&lt;/code&gt; assignment with the following command.&lt;/p&gt;

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

python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import os; print(os.urandom(24))"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;example output:&lt;/p&gt;

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

b&lt;span class="s1"&gt;'\x9a\xbb4\x86\x1d7\xac\x1ad\x14\xd9:\xcc\xf3\xf4\r\xf3\xd7\xd3cd\xfc$\xae'&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now we have to make a static directory to hold css and placeholder images, I wont be providing any code for this but this is folder is where you can house it for your project. If you don't use any style within your react application or the jinja templates. This is the command.&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;App/static


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

&lt;/div&gt;

&lt;p&gt;Now lets make a folder for templates inside the App directory to act as a place to put html and jinja template files. &lt;/p&gt;

&lt;p&gt;We will also make an index.html in the same command. &lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;App/templates &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;App/templates/index.html


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

&lt;/div&gt;

&lt;p&gt;We'll add simple html to use for testing if our flask app is working.&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
Hello world!
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now we need to make a views model. This is where you will keep python functions that are called when a user visits a url. &lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;App/views 


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

&lt;/div&gt;

&lt;p&gt;Next we need to make an __init__.py to access our views functions app wide and an index.py file to hold our function specific to the &lt;code&gt;'/'&lt;/code&gt; route.&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/views/index.py &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;App/views/__init__.py


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

&lt;/div&gt;

&lt;p&gt;Inside this index.py we will make our first flask function. &lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
index (main) view.

URLs include:
/
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;


&lt;span class="nd"&gt;@App.app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Display / route.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Inside the views/__init__.py we add the import. &lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Views, one for each App&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s page.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.index&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_index&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We will add a placeholder file model.py. Even though we wont add any code to it for the moment, eventually this file will house the code for the database connection. &lt;/p&gt;

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

 &lt;span class="nb"&gt;touch &lt;/span&gt;App/model.py


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

&lt;/div&gt;

&lt;p&gt;We still don't have a way for flask to understand that we have an App package to use. To fix this we will create a .toml file. &lt;/p&gt;

&lt;p&gt;in the project directory add this file. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;pyproject.toml


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

&lt;/div&gt;

&lt;p&gt;Add the following text to the &lt;em&gt;pyproject.toml&lt;/em&gt;. &lt;/p&gt;

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

&lt;span class="nn"&gt;[build-system]&lt;/span&gt;
&lt;span class="py"&gt;requires&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;["setuptools&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;64.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="err"&gt;wheel&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;build-backend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"setuptools.build_meta"&lt;/span&gt;

&lt;span class="nn"&gt;[project]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"App"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"arrow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"bs4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Flask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"requests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;requires-python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.10&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="nn"&gt;[tool.setuptools]&lt;/span&gt;
&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Double check that you are in your python virtual environment,&lt;br&gt;
now we have to install App into the virtual environment. &lt;/p&gt;

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

&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate


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

&lt;/div&gt;

&lt;p&gt;and then &lt;/p&gt;

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You should receive the following output. &lt;/p&gt;

&lt;p&gt;output:&lt;br&gt;
&lt;em&gt;a bunch of build info..&lt;/em&gt;&lt;br&gt;
&lt;em&gt;...&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Successfully built App&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Installing collected packages: App&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Successfully installed App-0.1.0&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;if everything was done correctly you should be able to see hello world by running the following command. &lt;/p&gt;

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

flask &lt;span class="nt"&gt;--app&lt;/span&gt; App &lt;span class="nt"&gt;--debug&lt;/span&gt; run &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 4000


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

&lt;/div&gt;

&lt;p&gt;and going to &lt;a href="http://localhost:4000/" rel="noopener noreferrer"&gt;localhost:4000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exit the terminal for the flask app by pressing &lt;code&gt;control + c&lt;/code&gt; when you are finished checking that you see hello world at the local host. &lt;/p&gt;

&lt;p&gt;In preparation to move onto the part where we connect the database to the App, we are going to make a run script so we don't have to type a long command in everytime we want to start the server. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch&lt;/span&gt; ./bin/run


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

&lt;/div&gt;

&lt;p&gt;And add the following code to the script.&lt;/p&gt;

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

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-Eeuo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;development
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;App
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;usage
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;



&lt;span class="c"&gt;# If var/App.sqlite3 does not exist, print an error and exit non-zero.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; var/App.sqlite3 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: var/App.sqlite3 does not exist. Run ./bin/db create."&lt;/span&gt;
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
    &lt;span class="k"&gt;fi


&lt;/span&gt;flask &lt;span class="nt"&gt;--app&lt;/span&gt; App &lt;span class="nt"&gt;--debug&lt;/span&gt; run &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 4000


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

&lt;/div&gt;

&lt;p&gt;Enable the script. &lt;/p&gt;

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

&lt;span class="nb"&gt;chmod&lt;/span&gt; +x bin/run


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

&lt;/div&gt;

&lt;p&gt;Run the script to ensure no errors were introduced. &lt;/p&gt;

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

./bin/run


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

&lt;/div&gt;

&lt;p&gt;You should now be able to visit &lt;a href="http://localhost:4000/" rel="noopener noreferrer"&gt;localhost:4000&lt;/a&gt; the same as before. &lt;/p&gt;

&lt;p&gt;let's start by resetting the database. &lt;/p&gt;

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

./bin/db reset


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

&lt;/div&gt;

&lt;p&gt;Ensure that you can interact with the database from the terminal first. &lt;/p&gt;

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

sqlite3 var/App.sqlite3 &lt;span class="s2"&gt;"SELECT fullname, email FROM developer;"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
&lt;em&gt;-- Loading resources from /Users/tallan/.sqliterc&lt;/em&gt;&lt;br&gt;
&lt;em&gt;fullname    email&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;----------  ------------------&lt;/em&gt;&lt;br&gt;
&lt;em&gt;John Doe    &lt;a href="mailto:john_doe@gmail.com"&gt;john_doe@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Jane Smith  &lt;a href="mailto:jane_smith@yahoo.c"&gt;jane_smith@yahoo.c&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Bob Johnso  bob_johnson@outloo&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Alice Will  alice_williams@hot&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Charlie Br  charlie_brown@gmai&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste the following code into the blank model.py file. &lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;App model (database) API.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dict_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Convert database row objects to a dictionary keyed on column name.

    This is useful for building dictionaries which are then used to render a
    template.  Note that this would be inefficient for large queries.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;col&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="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Open a new database connection.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sqlite_db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DATABASE_FILENAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite_db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_filename&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;row_factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dict_factory&lt;/span&gt;

        &lt;span class="c1"&gt;# Foreign keys have to be enabled per-connection.
&lt;/span&gt;
        &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PRAGMA foreign_keys = ON&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqlite_db&lt;/span&gt;


&lt;span class="nd"&gt;@App.app.teardown_appcontext&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;close_db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Close the database at the end of a request.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;sqlite_db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sqlite_db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sqlite_db&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sqlite_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sqlite_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Before we can display anything to the browser, we have to account for how to handle images. &lt;/p&gt;

&lt;p&gt;Let's make a file in the views folder called images.py&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/views/images.py


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

&lt;/div&gt;

&lt;p&gt;Add the following code to this file. &lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;  &lt;span class="n"&gt;send_from_directory&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;


&lt;span class="nd"&gt;@App.app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/uploads/&amp;lt;path:filename&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Download a file.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;send_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;UPLOAD_FOLDER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                               &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_attachment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&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;Now add this function to the view/__init__.py so that we can find files in the uploads folder. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;view/__init__.py&lt;/em&gt;&lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Views, one for each app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s page.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.index&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_index&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.images&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;download_file&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this file we have a way for flask to get reference images based on the string names stored in the database. &lt;/p&gt;

&lt;p&gt;Now &lt;strong&gt;change&lt;/strong&gt; the &lt;em&gt;views/index.py&lt;/em&gt; to have a database call for all users except one. &lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
index (main) view.

URLs include:
/
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;


&lt;span class="nd"&gt;@App.app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Display / route.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Connect to database
&lt;/span&gt;    &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Query database
&lt;/span&gt;    &lt;span class="n"&gt;logname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT  fullname, email, picture &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FROM developer &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WHERE fullname != ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logname&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="n"&gt;devs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;devs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;devs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And change the index.html to display that information with jinja. &lt;/p&gt;

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

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;DOCTYPE&lt;/span&gt; &lt;span class="n"&gt;html&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="n"&gt;html&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&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="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;devs&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;p&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="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;p&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="n"&gt;img&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{ url_for(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;download_file&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, filename=dev.picture) }}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100&lt;/span&gt;&lt;span class="sh"&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="n"&gt;br&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endfor&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;html&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;If our development server is on by running &lt;code&gt;./bin/run&lt;/code&gt;, when we visit &lt;a href="http://localhost:4000/" rel="noopener noreferrer"&gt;localhost:4000&lt;/a&gt; we should see the names of the developers from the server except John Doe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqpgfe5656vyk11wsz95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqpgfe5656vyk11wsz95.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This completes the flask portion of this tutorial. &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Making the react app.
&lt;/h2&gt;

&lt;p&gt;We are going to make our react app in a slightly different way that normal so that it will make the instantiation on AWS easier. Doing it this was will make it so that we can run the front-end and back-end with a single process.&lt;/p&gt;

&lt;p&gt;Let's jump in. &lt;/p&gt;

&lt;p&gt;Make sure that you have a version of &lt;a href="https://formulae.brew.sh/formula/node" rel="noopener noreferrer"&gt;node&lt;/a&gt; greater than 19.8.1&lt;/p&gt;

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

node &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;and &lt;a href="https://www.google.com/search?q=npm+install+homebrew&amp;amp;rlz=1C5CHFA_enUS905US906&amp;amp;sxsrf=AB5stBi8b3Uv0B32ZW6uY48kqYjKtMULSw%3A1690316889275&amp;amp;ei=WTDAZOWhEO-pptQPzs-YqAs&amp;amp;ved=0ahUKEwilsviN2aqAAxXvlIkEHc4nBrUQ4dUDCBA&amp;amp;uact=5&amp;amp;oq=npm+install+homebrew&amp;amp;gs_lp=Egxnd3Mtd2l6LXNlcnAiFG5wbSBpbnN0YWxsIGhvbWVicmV3MgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABhHGNYEGLADMgoQABiKBRiwAxhDMgoQABiKBRiwAxhDSMQDUABYAHABeAGQAQCYAQCgAQCqAQC4AQPIAQDiAwQYACBBiAYBkAYK&amp;amp;sclient=gws-wiz-serp" rel="noopener noreferrer"&gt;npm&lt;/a&gt; version greater than 9.5.1.&lt;/p&gt;

&lt;p&gt;this should have installed npm as a package with your node install. &lt;/p&gt;

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

npm &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now let's make an App/js folder to keep react components.&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;App/js


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

&lt;/div&gt;

&lt;p&gt;And a Index.js file to keep our dom root div. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/js/Index.js


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

&lt;/div&gt;

&lt;p&gt;And add the following code to this file. &lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&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;App&lt;/span&gt; &lt;span class="o"&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;And the App component which will be the starting point of all the react code. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/js/App.js


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

&lt;/div&gt;

&lt;p&gt;add the following code to the App.js file. &lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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


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

&lt;/div&gt;

&lt;p&gt;Next we need a package json to define all of the packages for webpack and react to use. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;package.json


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

&lt;/div&gt;

&lt;p&gt;Add this code to the package.json file. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"App front end"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"App/js/Index.jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awdeorio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@babel/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7.21.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@babel/plugin-transform-runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7.21.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7.20.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@babel/preset-react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7.18.6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@babel/runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7.21.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@cypress/grep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.1.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@types/react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18.0.28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@types/react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18.0.11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"babel-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^9.1.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eslint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=8.36.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start-server-and-test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tmp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.2.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=5.76.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"webpack-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=5.0.1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"latest-version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=2.29.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"prop-types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=15.8.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ts-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=9.4.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=5.0.2"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18.0.0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;Next, we want to make a package-lock.json from the package.json. &lt;/p&gt;

&lt;p&gt;To do this run the following command. &lt;/p&gt;

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

npm i &lt;span class="nt"&gt;--package-lock-only&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now run this command to make a node modules folder. &lt;/p&gt;

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

npm ci &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now we want to make sure that we have webpack with the right version. &lt;/p&gt;

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

npx webpack &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The output should look something like this but results may very slightly. &lt;/p&gt;

&lt;p&gt;output:&lt;/p&gt;

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

 System:
    OS: macOS 11.7.6
    CPU: (8) x64 Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz
    Memory: 276.08 MB / 16.00 GB
  Binaries:
    Node: 20.3.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.6.7 - /usr/local/bin/npm
  Browsers:
    Chrome: 115.0.5790.102
    Safari: 16.4.1
  Packages:
    babel-loader: ^9.1.2 =&amp;gt; 9.1.3 
    ts-loader: &amp;gt;=9.4.2 =&amp;gt; 9.4.4 
    webpack: &amp;gt;=5.76.2 =&amp;gt; 5.88.2 
    webpack-cli: &amp;gt;=5.0.1 =&amp;gt; 5.1.4 


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

&lt;/div&gt;

&lt;p&gt;We want create a root.html and make a root div for the react-dom to mount onto. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;App/templates/root.html


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;App/templates/root.html&lt;/em&gt;&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{ url_for('static', filename='js/bundle.js') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Plain old HTML and jinja2 nav bar goes here --&amp;gt;&lt;/span&gt;


        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Loading ...
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Load JavaScript --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{ url_for('static', filename='js/bundle.js') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This is telling the flask app to display whatever is in the bundle.js in the root div.&lt;/p&gt;

&lt;p&gt;We want to make a webpack.config.js to keep our build configurations for react.&lt;/p&gt;

&lt;p&gt;In the project directory run the following command. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;webpack.config.js


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

&lt;/div&gt;

&lt;p&gt;And add this code to the &lt;em&gt;webpack.config.js&lt;/em&gt;.&lt;/p&gt;

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

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;existsSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fs"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Set the entrypoint to Index.jsx by default, but Index.tsx if using TypeScript.&lt;/span&gt;
&lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./App/js/Index.js"&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="n"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./App/js/Index.ts"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./App/js/Index.ts"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;mode:&lt;/span&gt; &lt;span class="s"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;output:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/App/static/js/"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;filename:&lt;/span&gt; &lt;span class="s"&gt;"bundle.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nl"&gt;devtool:&lt;/span&gt; &lt;span class="s"&gt;"source-map"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;module:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;rules:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Test for js or jsx files&lt;/span&gt;
        &lt;span class="nl"&gt;test:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jsx&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Exclude external modules from loader tests&lt;/span&gt;
        &lt;span class="nl"&gt;exclude:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;loader:&lt;/span&gt; &lt;span class="s"&gt;"babel-loader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;options:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;presets:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"@babel/preset-react"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="nl"&gt;plugins:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"@babel/transform-runtime"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Support for TypeScript in optional .ts or .tsx files&lt;/span&gt;
        &lt;span class="nl"&gt;test:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tsx&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;use:&lt;/span&gt; &lt;span class="s"&gt;"ts-loader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;exclude:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nl"&gt;resolve:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;extensions:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;".js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".tsx"&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;Compile the react code in preparation for a run test.&lt;/p&gt;

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

npx webpack


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

&lt;/div&gt;

&lt;p&gt;In the same way that we made a index.py we want to make a root.py to display the react app. &lt;/p&gt;

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

touch App/views/root.py


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

&lt;/div&gt;

&lt;p&gt;Add the following code. &lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
root of react app.

URLs include:
/root/
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;


&lt;span class="nd"&gt;@App.app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/root/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_root&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Display / root for react application.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Connect to database
&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now add this function to the __init__.py &lt;strong&gt;within the views&lt;/strong&gt; folder. the whole file will look like this. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;App/views/__init__.py&lt;/em&gt;&lt;/p&gt;

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

&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Views, one for each app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s page.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.index&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_index&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.root&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_root&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;App.views.images&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;download_file&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You should not receive any errors but might get warnings. &lt;/p&gt;

&lt;p&gt;Use the script we made earlier to run the flask app.&lt;/p&gt;

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

./bin/run


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

&lt;/div&gt;

&lt;p&gt;You should not get an error visit &lt;a href="http://localhost:4000/root" rel="noopener noreferrer"&gt;localhost:4000/root&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also ensure that our jinja index page still has our developer names. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxk9d6idqqux2geazyajg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxk9d6idqqux2geazyajg.png" alt="site that says 'hello react!'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you want to develop and make changes to the the react app and not type &lt;code&gt;npx webpack&lt;/code&gt; everytime, you can use the &lt;code&gt;--watch&lt;/code&gt; flag. this will work the same way as &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After we are finished checking the browser. Let's shut down the flask app by clicking on the terminal and pressing &lt;code&gt;control + c&lt;/code&gt;.&lt;/p&gt;

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

npx webpack &lt;span class="nt"&gt;--watch&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;npm packages can be installed as normal with &lt;code&gt;npm i &amp;lt;package-name&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The only major difference between how you interact with this react app vs. one mode with create-react-app is the front-end is essentially ran through the back-end.&lt;/p&gt;

&lt;p&gt;We are now ready to develop a front-end with react and a back-end with flask.&lt;/p&gt;

&lt;p&gt;We can also make jinja templates in this app when the situation fits. &lt;/p&gt;

&lt;p&gt;This completes the react portion of this tutorial. &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Setting up an AWS account.
&lt;/h2&gt;

&lt;p&gt;Its a good idea to check out the &lt;a href="https://aws.amazon.com/iam/resources/best-practices/" rel="noopener noreferrer"&gt;best practices&lt;/a&gt; for setting up AWS accounts since this is easy to forget about account security after you have had an account for a while. &lt;/p&gt;

&lt;p&gt;Before we can deploy to AWS we first have to set up an aws account. If you already have an account set up, sign into your AWS account you can skip this section by clicking here&lt;/p&gt;

&lt;p&gt;Go to this url to &lt;a href="https://portal.aws.amazon.com/billing/signup#/start/email" rel="noopener noreferrer"&gt;create an account&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x6kar6sjsp2dsj2gbxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x6kar6sjsp2dsj2gbxs.png" alt="AWS account signup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They will send a verification code to your email. &lt;/p&gt;

&lt;p&gt;After entering the code you will enter the will have to make a password. &lt;/p&gt;

&lt;p&gt;Then you will be sent to this page. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bzzazxgd6v1cjpdn2dv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bzzazxgd6v1cjpdn2dv.png" alt="AWS personal form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will need to add a credit card to your account even though the setup we are making is free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x3hl7ahg1em7papns8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x3hl7ahg1em7papns8k.png" alt="AWS billing page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Confirm your Identity. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ob1poryz3xf8a1ujg67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ob1poryz3xf8a1ujg67.png" alt="AWS confirm Identity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you confirm your phone number, choose which tier. We will use the free tier. Any tier you use will not effect the rest of this tutorial. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywdfbf42q7rydqcqzfjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywdfbf42q7rydqcqzfjd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will redirect you to your AWS sign-in. &lt;/p&gt;

&lt;p&gt;Log into you account and you will be directed to this page. &lt;/p&gt;

&lt;p&gt;Click on the settings icon in the top left corner of the page. &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhqcgiglcor92scclw93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhqcgiglcor92scclw93.png" alt="AWS dashboard with arrows to the settings tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstih6j7gikgcya3ougsa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstih6j7gikgcya3ougsa.png" alt="settings dash board with arrows to point to what to click on."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click to launch a new instance. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd8plb5pa315l2gxzw64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd8plb5pa315l2gxzw64.png" alt="arrow to launch instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are going to use an ubuntu instance. Click on Ubuntu where you see all the different virtual boxes. &lt;/p&gt;

&lt;p&gt;Scroll down to where it says add a key pair(login) and name it.&lt;/p&gt;

&lt;p&gt;If you start typing in the text box, a modal will popup where you can enter the name of the key. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm36521vpfh4dia87d5ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm36521vpfh4dia87d5ps.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether you added a key pair in the model or added directly to the textbox does not matter. As long as we choose RSA and .pem this will be fine. &lt;/p&gt;

&lt;p&gt;Click add key pair once you named it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gh9rkocq4yqdq41o8fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gh9rkocq4yqdq41o8fg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will download a aws-tutorial.pem file to you computer. &lt;/p&gt;

&lt;p&gt;Scroll down to network settings. &lt;/p&gt;

&lt;p&gt;Click on Allow HTTP traffic. &lt;strong&gt;This part is important because you will be able to do everything else in this tutorial but wont be able to ever see the website even though you did everything else right!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;You can also allow HTTPS traffic but I have not tested this. you will need to buy an SSL certificate too. If someone gets this to work with allowing https traffic please let us know in the comments and how to do it. &lt;/p&gt;

&lt;p&gt;Now click launch instance. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p4ce8t1c64y8frg5yji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p4ce8t1c64y8frg5yji.png" alt="arrow to launch instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll to the bottom and click view all instances. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yfcpssj0nv8rfvyaou0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yfcpssj0nv8rfvyaou0.png" alt="arrow to view all instances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be forwarded to a page with information about all of your instances. When you click the checkbox for the instance you just created, information about that instance will be displayed on the bottom of the page. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77e449hgqo3fg3dob1hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77e449hgqo3fg3dob1hw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you go the the address it will try and load for a while but no website will pop up. &lt;/p&gt;

&lt;p&gt;We will add the code from the previous parts of this section to be the website in the next section. &lt;/p&gt;

&lt;p&gt;This completes the AWS console setup portion of this tutorial. &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 5: Deploying to AWS.
&lt;/h2&gt;

&lt;p&gt;This is the most complex portion the tutorial. &lt;strong&gt;Be sure to read carefully&lt;/strong&gt; because a small error in this section can cause hours of headache if you don't do this step by step. But at the end of this you will have a website ready for development, live on the internet and the ability to deploy other websites the same way. &lt;/p&gt;

&lt;p&gt;If you stuggled with earlier parts of this tutorial, you can copy &lt;a href="https://github.com/TallanGroberg/aws-deploy-tutorial" rel="noopener noreferrer"&gt;my repo&lt;/a&gt; to make sure that none of the errors are from any previous sections which can make debugging easier. &lt;/p&gt;

&lt;p&gt;I recommend trying to do this on your own first.&lt;/p&gt;

&lt;p&gt;First thing is to make a github repo. &lt;/p&gt;

&lt;p&gt;for extra data safety make a .gitignore file and add the .pem file to it. &lt;/p&gt;

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

&lt;span class="nb"&gt;touch&lt;/span&gt; .gitignore


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

&lt;/div&gt;

&lt;p&gt;we want to add a lot folders to the gitignore since most of these are boilerplate files and not files that we have created. &lt;/p&gt;

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

*.pem
node_modules
env
App.egg-info
__pycache__


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

&lt;/div&gt;

&lt;p&gt;This will prevent any private keys from being published to github. &lt;/p&gt;

&lt;p&gt;make an initial repo&lt;/p&gt;

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

git init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git add &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"initialize"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;create a &lt;a href="https://www.google.com/search?q=remote+repository&amp;amp;rlz=1C5CHFA_enUS905US906&amp;amp;oq=remote+repository+&amp;amp;aqs=chrome..69i57j0i512l9.8710j0j7&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8" rel="noopener noreferrer"&gt;remote origin&lt;/a&gt; and push it to github, which you will have to do on your own, leave it public for now, at least until you pull it into your ubuntu instance which we will do shortly. Then you can make it private if you wish. &lt;/p&gt;

&lt;p&gt;If you completed the previous sections, you should have a aws-tutorial.pem file in your downloads folder. &lt;/p&gt;

&lt;p&gt;Ensure you are in your project directory of your local repo, then run the following command. &lt;/p&gt;

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

&lt;span class="nb"&gt;mv&lt;/span&gt; ~/Downloads/aws-tutorial.pem &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;we can also drag and drop into the project directory. As long as we have it in the root of this folder of your &lt;strong&gt;local&lt;/strong&gt; repo, we are fine. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsq2te4x6i5nivx71smq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsq2te4x6i5nivx71smq.png" alt="code showing .pem file is in the project directory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we give this a special &lt;a href="https://www.google.com/search?q=chmod+400+permissions&amp;amp;rlz=1C5CHFA_enUS905US906&amp;amp;oq=chmod+400+permissions&amp;amp;aqs=chrome..69i57j0i22i30l2j0i390i650l4.8527j0j7&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8" rel="noopener noreferrer"&gt;400 permission&lt;/a&gt; to the aws-tutorial.pem file for read only access so that we don't modify our key to the aws instance. &lt;/p&gt;

&lt;p&gt;Run this command. &lt;/p&gt;

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

&lt;span class="nb"&gt;chmod &lt;/span&gt;400 aws-tutorial.pem


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

&lt;/div&gt;

&lt;p&gt;We are now going to tunnel into our aws instance which will take use to a ubuntu terminal on aws that we control from our host machine. &lt;/p&gt;

&lt;p&gt;To do this you want to run the following command. &lt;/p&gt;

&lt;p&gt;Do not include the &amp;lt;&amp;gt;'s in the command but do include the ubuntu@&lt;/p&gt;

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

ssh &lt;span class="nt"&gt;-i&lt;/span&gt; aws-tutorial.pem ubuntu@&amp;lt;your public ipv4 DNS from the AWS cosole&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;we can copy and past from our AWS console like so. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6r7q0kq6qejy9mja1jgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6r7q0kq6qejy9mja1jgp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

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

ssh &lt;span class="nt"&gt;-i&lt;/span&gt; aws-tutorial.pem ubuntu@&amp;lt;&lt;span class="nb"&gt;paste &lt;/span&gt;what you just copied here&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Type yes and enter to finish connecting. &lt;/p&gt;

&lt;p&gt;You should have a proper ssh tunnel to your ubuntu instance. It should look like this.&lt;/p&gt;

&lt;p&gt;If it didn't work. Make sure that you have your aws-tutorial.pem file in the project directory. That you ran &lt;code&gt;chmod 400 aws-tutorial.pem&lt;/code&gt; and that the command &lt;code&gt;ssh -i aws-tutorial.pem ubuntu@&amp;lt;public ipV4 DNS&amp;gt;&lt;/code&gt; is correct and without the angle brackets. Note that everytime you shut down and restart you instance you will have to recopy this public ipV4 DNS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwmf9s5jkg13a3uarevu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwmf9s5jkg13a3uarevu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we are now going to be working with a linux command line interface, the commands will be a bit different. &lt;/p&gt;

&lt;p&gt;Now we want to install &lt;a href="https://en.wikipedia.org/wiki/Nginx" rel="noopener noreferrer"&gt;nginx&lt;/a&gt; which will give our ubuntu server a way host a website. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update


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

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;nginx


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

&lt;/div&gt;

&lt;p&gt;type Y to add nginx. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3im2w3ir297uc25548o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3im2w3ir297uc25548o.png" alt="accepting nginx on commandline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;when you visit the site remember to make sure that it's &lt;code&gt;http::/&lt;/code&gt; and not &lt;code&gt;https::/&lt;/code&gt; when you do, you should see this page now. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iilrkyi9bfpxd7ow4xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iilrkyi9bfpxd7ow4xf.png" alt="nginx default page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are going to have to change some files to get a configuration for our app to work correctly with njinx. &lt;/p&gt;

&lt;p&gt;To accomplish this we will use &lt;a href="https://www.google.com/search?q=emacs+cheat+sheet+mac&amp;amp;rlz=1C5CHFA_enUS905US906&amp;amp;oq=emacs+cheat+sheet&amp;amp;aqs=chrome.1.69i57j0i512l2j0i22i30l7.9144j0j7&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8" rel="noopener noreferrer"&gt;emacs&lt;/a&gt; to alter files. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;emacs-nox


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

&lt;/div&gt;

&lt;p&gt;Accept this install like last time. &lt;/p&gt;

&lt;p&gt;Also run this command. &lt;/p&gt;

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

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;emacs


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

&lt;/div&gt;

&lt;p&gt;This command will give no output. &lt;/p&gt;

&lt;p&gt;Having emacs means we will be using nano. &lt;/p&gt;

&lt;p&gt;Check that we have it.&lt;/p&gt;

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

which nano


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
/usr/bin/nano&lt;/p&gt;

&lt;p&gt;Now we will create a nginx.conf file to define how nginx will interact with our web app. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/nginx.conf


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

&lt;/div&gt;

&lt;p&gt;For reference, when I write &lt;code&gt;control + k&lt;/code&gt; the plus is to indicate that you press control and k keys at the same time. &lt;/p&gt;

&lt;p&gt;Hold &lt;code&gt;control + k&lt;/code&gt; in order to delete all the lines in the file line by line. &lt;/p&gt;

&lt;p&gt;after the file is completely blank, copy and paste this text using &lt;code&gt;control + v&lt;/code&gt;&lt;/p&gt;

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

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Run&lt;/span&gt; &lt;span class="nx"&gt;nginx&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="nx"&gt;processes&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;which&lt;/span&gt; &lt;span class="nx"&gt;should&lt;/span&gt; &lt;span class="nx"&gt;have&lt;/span&gt; &lt;span class="nx"&gt;been&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;installing&lt;/span&gt; &lt;span class="nx"&gt;Nginx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Start&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;workers&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;there&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;CPU&lt;/span&gt; &lt;span class="nx"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;worker_processes&lt;/span&gt; &lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Configure&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="nx"&gt;processing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Maximum&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;simultaneous&lt;/span&gt; &lt;span class="nx"&gt;connections&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="nx"&gt;worker&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;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Configure&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Directly&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="nx"&gt;between&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;descriptors&lt;/span&gt; &lt;span class="nx"&gt;instead&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;storing&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;sendfile&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Send&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;beginning&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;single&lt;/span&gt; &lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;tcp_nopush&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;MIME&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;include&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;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;mime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Specify&lt;/span&gt; &lt;span class="nx"&gt;where&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt; &lt;span class="nx"&gt;should&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;written&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;access_log&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="sr"&gt;/log/&lt;/span&gt;&lt;span class="nx"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;access&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;error_log&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="sr"&gt;/log/&lt;/span&gt;&lt;span class="nx"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Compress&lt;/span&gt; &lt;span class="nx"&gt;HTML&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="nx"&gt;sending&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;gzip&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Include&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;specific&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;include&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;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="cm"&gt;/*.conf;
}


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

&lt;/div&gt;

&lt;p&gt;Then press &lt;code&gt;control + x&lt;/code&gt; then &lt;code&gt;y&lt;/code&gt; for saving the file and &lt;code&gt;enter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will bring you back to the ubuntu terminal with the green text. &lt;/p&gt;

&lt;p&gt;Now we want to add special configuration details specific to our App itself. &lt;/p&gt;

&lt;p&gt;This will be a similar process as we just did but, we will be creating this file. &lt;/p&gt;

&lt;p&gt;Type this command into the terminal. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/conf.d/App.conf


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

&lt;/div&gt;

&lt;p&gt;Copy and paste this file. &lt;/p&gt;

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

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Configure&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;virtual&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;We&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;need&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;because&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;machine&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;single&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Configure&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Send&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;subrequest&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;accounts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proceed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s 403, don&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;just&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;auth_request&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Serve&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;requested&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="o"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;filename&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;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="sr"&gt;/www&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Configure&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;specific&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/accounts/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Forward&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;Flask&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="nx"&gt;proxy_pass&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:8000;&lt;/span&gt;

        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Don&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t include the body of the request if any in the proxied request.
        proxy_pass_request_body off;

        # Set some headers that Nginx wants us to use for authentication subrequests.
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }

    # Configure all other requests to the server besides the ones that match above.
    location / {
        # Forward the request to http://localhost:8000 and return its response to the client.
        proxy_pass http://localhost:8000;

        # Make sure the proxied request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;Host&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;what&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="nx"&gt;intended&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="nx"&gt;proxy_set_header&lt;/span&gt; &lt;span class="nx"&gt;Host&lt;/span&gt; &lt;span class="nx"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;proxied&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;indicating&lt;/span&gt; &lt;span class="nx"&gt;whether&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;HTTPS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="nx"&gt;proxy_set_header&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Proto&lt;/span&gt; &lt;span class="nx"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;proxied&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;specifying&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;IP&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="nx"&gt;proxy_set_header&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;For&lt;/span&gt; &lt;span class="nx"&gt;$proxy_add_x_forwarded_for&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;there are some configurations in this tutorial that are based on the idea that this app will be much more heavy duty than what is given in this tutorial. Try uncommenting lines of code when you implement auth.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;control + x&lt;/code&gt; then &lt;code&gt;y&lt;/code&gt; then &lt;code&gt;enter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we want to restart the nginx server. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx


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

&lt;/div&gt;

&lt;p&gt;Install our python environment. &lt;/p&gt;

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

 &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;python3 python3-venv sqlite3


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

&lt;/div&gt;

&lt;p&gt;Now clone your remote repository. Alternatively you can use &lt;a href="https://github.com/TallanGroberg/aws-deploy-tutorial.git" rel="noopener noreferrer"&gt;my repo&lt;/a&gt;&lt;/p&gt;

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

git clone https://github.com/TallanGroberg/aws-deploy-tutorial.git


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

&lt;/div&gt;

&lt;p&gt;Create a virtual environment for your project instance. &lt;/p&gt;

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

python3 &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
3.10.6&lt;/p&gt;

&lt;p&gt;This is fine if its different that our local machine but it has to still be greater that 3.10&lt;/p&gt;

&lt;p&gt;cd into your folder. &lt;/p&gt;

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

&lt;span class="nb"&gt;cd &lt;/span&gt;aws-tutorial


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

&lt;/div&gt;

&lt;p&gt;We have one more file to change. Since we changed the default location for uploads in production. we have to alter our App's config.py to reference var/www instead of var/uploads. &lt;/p&gt;

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

nano App/config.py


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge5hiya2ykmsv33c3c2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge5hiya2ykmsv33c3c2o.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use your mouse to scroll to a single line. And should be able to erase and type like in more common text editors. &lt;/p&gt;

&lt;p&gt;We should change &lt;code&gt;UPLOADS_FOLDER&lt;/code&gt; to be this now. &lt;/p&gt;

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

UPLOADS_FOLDER &lt;span class="o"&gt;=&lt;/span&gt; pathlib.Path&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/var/www/uploads'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then press &lt;code&gt;control + x&lt;/code&gt; then &lt;code&gt;Y&lt;/code&gt; and finally &lt;code&gt;enter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create the virtual environment. &lt;/p&gt;

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

python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And activate. &lt;/p&gt;

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

&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate


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

&lt;/div&gt;

&lt;p&gt;(env) should be at the left side of the green text. &lt;/p&gt;

&lt;p&gt;Run each of these commands one by one. &lt;/p&gt;

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip setuptools wheel


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

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt


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

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This next command to install &lt;a href="https://en.wikipedia.org/wiki/Gunicorn" rel="noopener noreferrer"&gt;gunicorn&lt;/a&gt; will enable us to run a local server like in development but in production.&lt;/p&gt;

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

pip &lt;span class="nb"&gt;install &lt;/span&gt;gunicorn


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

&lt;/div&gt;

&lt;p&gt;Now we initialize the database.&lt;/p&gt;

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

./bin/db create


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

&lt;/div&gt;

&lt;p&gt;Copy the uploads folder to the var/www folder where nginx can use it.&lt;/p&gt;

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

 &lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; var/uploads /var/www


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

&lt;/div&gt;

&lt;p&gt;Give ubuntu permissions for this new directory&lt;/p&gt;

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

&lt;span class="nb"&gt;sudo chown &lt;/span&gt;ubuntu:www-data /var/www/uploads


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

&lt;/div&gt;

&lt;p&gt;Now we install react related packages starting with npm and node. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;nodejs npm


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

&lt;/div&gt;

&lt;p&gt;You will notice that we don't have the same node version. &lt;/p&gt;

&lt;p&gt;When you see pink screens durning package downloads just press enter to get through them. They didn't cause me any problems when I picked the default everytime. &lt;/p&gt;

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

node &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
v12.22.9&lt;/p&gt;

&lt;p&gt;Now we want to install everything from our &lt;strong&gt;package.json&lt;/strong&gt;&lt;/p&gt;

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

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;just to be sure make sure that your package-lock.json is here. &lt;/p&gt;

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

npm i &lt;span class="nt"&gt;--package-lock-only&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When this download is happening, we can see that we get alot of versioning warings. This will have to be addressed by updating node version manager, you can check out the github here (&lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;nvm&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Run and update for ubuntu. &lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update


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

&lt;/div&gt;

&lt;p&gt;Install the version manager from its github directly. &lt;/p&gt;

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

curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash


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

&lt;/div&gt;

&lt;p&gt;Now we have to source it to make sure ubuntu can take advantage of it. &lt;/p&gt;

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

&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc


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

&lt;/div&gt;

&lt;p&gt;This will cause us the have to reactivate our python environment this means that we have to reinstantiate the whole package. &lt;/p&gt;

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

&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate


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

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip setuptools wheel


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

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt


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

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

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now we just install the node version that we had our react app running on in development. &lt;/p&gt;

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

nvm &lt;span class="nb"&gt;install &lt;/span&gt;v20.3.0


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

&lt;/div&gt;

&lt;p&gt;Make sure that the node version update. &lt;/p&gt;

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

node &lt;span class="nt"&gt;-v&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;output:&lt;br&gt;
&lt;em&gt;v20.3.0&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This should ensure that when we run webpack without any errors. &lt;/p&gt;

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

npx webpack


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

&lt;/div&gt;

&lt;p&gt;You should receive a compiled successfully in the last line of the output. &lt;/p&gt;

&lt;p&gt;We want to install &lt;code&gt;javascript-obfuscator&lt;/code&gt; to make our javascript harder to understand for hackers. &lt;/p&gt;

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

npm &lt;span class="nb"&gt;install &lt;/span&gt;javascript-obfuscator


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

&lt;/div&gt;

&lt;p&gt;Now we run the next few commands to compile, obfuscate and replace our original build. &lt;/p&gt;

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

npx webpack


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

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

npx javascript-obfuscator App/static/js/bundle.js &lt;span class="nt"&gt;--reserved-strings&lt;/span&gt; &lt;span class="s1"&gt;'\s*'&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;press &lt;code&gt;y&lt;/code&gt; to proceed. &lt;/p&gt;

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

&lt;span class="nb"&gt;mv &lt;/span&gt;App/static/js/bundle-obfuscated.js App/static/js/bundle.js


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

&lt;/div&gt;

&lt;p&gt;Now we are going to get the server running.&lt;/p&gt;

&lt;p&gt;Before we try and run it make sure that no other gunicorn processes are running. &lt;/p&gt;

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

pkill &lt;span class="nt"&gt;-f&lt;/span&gt; gunicorn


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

&lt;/div&gt;

&lt;p&gt;When you run the next command, there should be no output.&lt;/p&gt;

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

pgrep &lt;span class="nt"&gt;-af&lt;/span&gt; gunicorn


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

&lt;/div&gt;

&lt;p&gt;Start the server in the background with this command. &lt;/p&gt;

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

gunicorn &lt;span class="nt"&gt;-b&lt;/span&gt; localhost:8000 &lt;span class="nt"&gt;-w&lt;/span&gt; 2 &lt;span class="nt"&gt;-D&lt;/span&gt; App:app


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

&lt;/div&gt;

&lt;p&gt;Now when you visit your aws site, you should be able to see the app running. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flc7doz52a0sq8330meus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flc7doz52a0sq8330meus.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it's not, we can trouble shoot with this command which will give the log level output of what is happening. &lt;/p&gt;

&lt;p&gt;first.&lt;/p&gt;

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

pkill &lt;span class="nt"&gt;-f&lt;/span&gt; gunicorn


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

&lt;/div&gt;

&lt;p&gt;then.&lt;/p&gt;

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

gunicorn &lt;span class="nt"&gt;-b&lt;/span&gt; localhost:8000 &lt;span class="nt"&gt;-w&lt;/span&gt; 2 App:app &lt;span class="nt"&gt;--log-level&lt;/span&gt; debug


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

&lt;/div&gt;

&lt;p&gt;If you get an error about packages missing pertaining to python redo the virtual environment installation. You can do the same for react and that should do the trick.&lt;/p&gt;

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

&lt;p&gt;I have not tried to develop anything beyond a single page react application with react with this configuration. I encourage comments about any react-packages that will not work with this configuration or if anyone could make the same functionality with create-react-app.&lt;/p&gt;

&lt;p&gt;There is a way to write a script so that this deploy is way commands in the terminal. A great exercise would be to make this script on your own. &lt;/p&gt;

&lt;p&gt;Let me know what I could add to this article in the comments. &lt;/p&gt;

</description>
      <category>sqlite</category>
      <category>react</category>
      <category>flask</category>
      <category>aws</category>
    </item>
    <item>
      <title>5 gamified learning experiences to learn Web Dev</title>
      <dc:creator>Chris Noring</dc:creator>
      <pubDate>Sun, 26 Jun 2022 23:11:51 +0000</pubDate>
      <link>https://dev.to/itnext/5-gamified-learning-experiences-to-learn-web-dev-450a</link>
      <guid>https://dev.to/itnext/5-gamified-learning-experiences-to-learn-web-dev-450a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Does learning have to be boring, not in my opinion. I'm sure you also agree that you learn better if you have fun. Here's a list of 5 gamified experiences that will help you learn web development.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://flexboxfroggy.com/"&gt;Flexbox froggy&lt;/a&gt;. Learn to navigate a frog by and learn about Flexbox at the same time.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://education.minecraft.net/"&gt;Minecraft Education&lt;/a&gt; You have code window that helps you affect the world in Minecraft, who doesn't want to build things faster? Blocks, JavaScript as well as Python available.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://codecombat.com/"&gt;CodeCombat&lt;/a&gt; Imagine using code to take yourself through dungeons. This might look like it's made for 10 year olds but I had a ton of fun :)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.twilio.com/quest"&gt;Twilio Quest&lt;/a&gt; This is seriously good. Travelling the Universe while learning JavaScript, Python and Twilio API, sounds pretty good to me.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arcade.makecode.com/#"&gt;MakeCode arcade - skillmaps&lt;/a&gt; You learn to build various games while being introduced to coding. You may start with blocks, but you will be able to advance to JavaScript or Python prettty quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a ton of these gamified platforms so I would love to hear your favourite in the comments and why :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I wrote a free book on React</title>
      <dc:creator>Chris Noring</dc:creator>
      <pubDate>Sun, 19 Jun 2022 19:47:56 +0000</pubDate>
      <link>https://dev.to/itnext/i-wrote-a-free-book-on-react-iee</link>
      <guid>https://dev.to/itnext/i-wrote-a-free-book-on-react-iee</guid>
      <description>&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7o4gsvz5cl0xn5oeg3s9.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7o4gsvz5cl0xn5oeg3s9.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/chris_noring" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, happy to take your suggestions on topics or improvements /Chris&lt;/p&gt;

&lt;p&gt;I'm writing a free book on React, it will always be free :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://softchris.github.io/react-book/#/" rel="noopener noreferrer"&gt;Book link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/softchris/react-book" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; in case you want to contribute&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Video course
&lt;/h3&gt;

&lt;p&gt;It's also available as a video course (just started, but please comment in you're excited about seeing more parts)&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Content
&lt;/h2&gt;

&lt;p&gt;Hope you enjoy it :)&lt;/p&gt;

&lt;p&gt;It covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basics&lt;/li&gt;
&lt;li&gt;Forms&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lot of my articles here is based on things I wrote in the book. Hope it can help someone :)&lt;/p&gt;

</description>
      <category>react</category>
      <category>book</category>
      <category>testing</category>
      <category>patterns</category>
    </item>
    <item>
      <title>How YOU can build a GraphQL API with Apollo</title>
      <dc:creator>Chris Noring</dc:creator>
      <pubDate>Sun, 05 Jun 2022 00:50:27 +0000</pubDate>
      <link>https://dev.to/itnext/creating-a-graphql-server-with-apollo-1f4e</link>
      <guid>https://dev.to/itnext/creating-a-graphql-server-with-apollo-1f4e</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ax_h-6qW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AzhVHPUEyp_x3wpba3IWQCg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ax_h-6qW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AzhVHPUEyp_x3wpba3IWQCg.jpeg" alt="" width="600" height="600"&gt;&lt;/a&gt;&lt;br&gt;
Follow me on &lt;a href="https://twitter.com/chris_noring"&gt;Twitter&lt;/a&gt;, happy to take your suggestions on topics or improvements /Chris&lt;/p&gt;

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

&lt;p&gt;This article is part of a series on GraphQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/softchris/building-a-graphql-server-with-nodejs-andexpress-5hfh"&gt;Building a GraphQL server using Node.js and Express&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Building a GraphQL server using Node.js and the Apollo Framework, &lt;strong&gt;we are here&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/softchris/consuming-an-apollo-graphql-server-usingreact-3kk4"&gt;Consuming an Apollo GraphQL server using React&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphQL is a new way we can use to build APIs. One of its prominent features is content-negotiation, a way for the client to tell the backend exactly what fields it needs and at what depth. This enables you to get a smaller payload of data back, which can really make a difference on a bad network connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Apollo is an entire platform for handling the backend as well as the client-side when using GraphQL and can even help you in the cloud. It’s well worth checking out &lt;a href="https://www.apollographql.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article will be about how to create a GraphQL server using Apollo and thus only using a small part of what the Apollo platform can do. As you will see it’s pretty easy. I hope you enjoy the read :)&lt;/p&gt;

&lt;p&gt;In this article we will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install and set up&lt;/strong&gt;, we will learn how to install &lt;code&gt;apollo-graphql&lt;/code&gt; and &lt;code&gt;graphql&lt;/code&gt; libraries needed to created our server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define a schema and resolvers&lt;/strong&gt;, a Schema is needed to describe our types. Resolvers are functions that are invoked to handle queries from the user. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt;, when we start our server we can do so in a debug mode so we get a browser page we can interact with and that will help us send our queries to our server and it will also show us the results &lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Some of the below links are introductory so you can learn more after having read this article and some are more advanced once you feel you've grasped Graphql better.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/"&gt;Apollo project landing page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/docs/tutorial/schema.html"&gt;Building a schema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/docs/tutorial/resolvers.html"&gt;How to write Resolvers for your server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/docs/apollo-server/v1/servers/azure-functions.html"&gt;Using GraphQL with Azure Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/blog/use-graphql-with-hasura-and-azure-database-for-postgresql/?wt.mc_id=devto-blog-chnoring"&gt;Using GraphQL on Azure generally&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install and set up
&lt;/h2&gt;

&lt;p&gt;To create a GraphQL server using Apollo Server we need to do three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;  &lt;strong&gt;install&lt;/strong&gt; &lt;code&gt;apollo-server&lt;/code&gt; and &lt;code&gt;graphql&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;define&lt;/strong&gt; a schema&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;define&lt;/strong&gt; resolvers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s install the needed dependencies:&lt;/p&gt;

&lt;pre id="bed8"&gt;npm install --save apollo-server graphql&lt;/pre&gt;

&lt;p&gt;Once we have done that we are able to proceed with the next steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Define a schema
&lt;/h3&gt;

&lt;p&gt;To define a schema we need to be using a function called &lt;code&gt;gql&lt;/code&gt; that allows us to define a schema like a multiline template string and most importantly using the GraphQL query language.&lt;/p&gt;

&lt;p&gt;First, we import &lt;code&gt;gql&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apollo-server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up we can start defining the schema itself:&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;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  type Query {
    products: [Product]
    product(id: Int!): Product
  }
  type Product {
    id: Int,
    name: String,
    description: String
  }
  input ProductInput {
    name: String,
    description: String
  }
  type Mutation {
    login(email: String): String # token
    createProduct(product: ProductInput)
  }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we export the schema for later usage&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="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full file should now look like this:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apollo-server&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;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  type Query {
    products: [Product]
    product(id: Int!): Product
  }
  type Product {
    id: Int,
    name: String,
    description: String
  }
  input ProductInput {
    name: String,
    description: String
  }
  type Mutation {
    login(email: String!): String # token
    createProduct(product: ProductInput): String
  }
`&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define resolvers
&lt;/h3&gt;

&lt;p&gt;Next up we need to define what the following queries and mutations should do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;products&lt;/strong&gt;, this should return a list of products&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;product(id: Int!)&lt;/strong&gt;, this should return one product&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;login(email: String)&lt;/strong&gt;, this should log in the user&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;createProduct(product: ProductInput)&lt;/strong&gt;, this should create a product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start a new file &lt;code&gt;resolvers.js&lt;/code&gt;. At this point, we will keep things simple and have some local static data but we could improve this server by having it call a database or an API. So let’s define some static data at the top:&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;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that Apollo server expects a certain type of object back with the following shape:&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;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&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;Not the two keywords &lt;code&gt;Query&lt;/code&gt; and &lt;code&gt;Mutation&lt;/code&gt; above. These two are objects and we need to define each corresponding resolver function. Let’s start by adding a resolver function for products:&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;getProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;products&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&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;A comment on &lt;code&gt;getProducts()&lt;/code&gt; method is that we return a &lt;code&gt;Promise&lt;/code&gt;. Now, we could return our &lt;code&gt;products&lt;/code&gt; list directly but this is just a way to showcase that we can return an asynchronous response as well, which means this will fit well with us talking to a 3rd party API or doing a lookup on a database. To go along with our &lt;code&gt;Promise&lt;/code&gt; response we mark it with &lt;code&gt;async&lt;/code&gt; in our return object.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Define a resolver function with a parameter&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We’ve learned how to define a resolver function, and now let’s look at how we can grab a parameter from the user request and query our backend based on it.&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;getProductById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;products&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;product&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProductById&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="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;Above we added &lt;code&gt;product&lt;/code&gt; to our &lt;code&gt;Query&lt;/code&gt; object and as you can see we can quite easily dig out the &lt;code&gt;id&lt;/code&gt; from the user request.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Define a resolver function for a mutation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To define resolvers for mutations we need to introduce a &lt;code&gt;Mutation&lt;/code&gt; property on our exported object, just like we needed to introduce &lt;code&gt;Query&lt;/code&gt;. So now our code should look like this:&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;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;products&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;product&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProductById&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the addition of &lt;code&gt;Mutation&lt;/code&gt; above.&lt;/p&gt;

&lt;p&gt;The next step is to add our &lt;code&gt;createProduct&lt;/code&gt; property and a resolver function that handles that, like so:&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;createProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;products&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;product&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProductById&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;createProduct&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;createProduct&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;      &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Putting it all together&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now we have defined a set of resolver functions, let’s have a look at the resulting code in its entirety:&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;products&lt;/span&gt; &lt;span class="o"&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;getProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&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;getProductById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&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;createProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;products&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;product&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProductById&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;createProduct&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;createProduct&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;   &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we have only operated on static data but we could easily switch those calls to target a database or a 3rd party API, that’s entirely up to you. As long as you remember to use the &lt;code&gt;await&lt;/code&gt; keyword in your resolver definition you are good to go with interacting with anything return a &lt;code&gt;Promise&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Start the server&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have defined a schema and a set of resolver functions. Now let’s import &lt;code&gt;schema.js&lt;/code&gt; and &lt;code&gt;resolvers.js&lt;/code&gt; and kick off our server:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apollo-server&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;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./schema&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;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./resolvers&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🚀 Server ready at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Debug&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Navigate to &lt;code&gt;http://localhost:4000&lt;/code&gt; —&lt;/p&gt;

&lt;p&gt;you should have something looking like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FKE8v-Qi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Ap374DSjbjXIiYTCvMk74Jw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKE8v-Qi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Ap374DSjbjXIiYTCvMk74Jw.png" alt="" width="880" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see this looks very much like the GraphiQL environment we presented in the chapter &lt;a href="https://medium.com/@noringc/building-a-graphql-server-with-node-js-and-express-f8ea78e831f9"&gt;GraphQL + Node.js Express&lt;/a&gt;. The idea is the same. On your left you have an area where you can enter &lt;code&gt;queries&lt;/code&gt; and &lt;code&gt;mutations&lt;/code&gt; and on your right is the results area. On the bottom left is a&lt;code&gt;variables&lt;/code&gt; area that allows you to specify input variables that you can use the top left pane.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Example usage&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let’s try to create a &lt;code&gt;query&lt;/code&gt;. We can do so in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;using&lt;/strong&gt; the no-keyword version, &lt;code&gt;{}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;using&lt;/strong&gt; the keyword &lt;code&gt;query&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first variant looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CeKrAGmS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2ADCPCUlM32UN2be354dIpRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CeKrAGmS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2ADCPCUlM32UN2be354dIpRw.png" alt="" width="880" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above we are only using &lt;code&gt;{}&lt;/code&gt; to specify our query and then we query for a resource &lt;code&gt;launches&lt;/code&gt; and drills down into the resource to get the columns that we need, i.e &lt;code&gt;mission&lt;/code&gt; and under &lt;code&gt;mission&lt;/code&gt; we grab the column &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s try to use the other query variant next by using the keyword &lt;code&gt;query&lt;/code&gt;. The keyword query allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Name&lt;/strong&gt; the query so we can refer to it later&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Specify more than one query&lt;/strong&gt; in the same window, so we can choose which one we want at a given point in time&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Specify a parameter&lt;/strong&gt; for our query ( we will show this one in our next example )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---p9tNtkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AZbQt75zef5UsHosMzp7aHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---p9tNtkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AZbQt75zef5UsHosMzp7aHg.png" alt="" width="880" height="1112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above we managed to specify two different queries and have given them the name &lt;code&gt;LaunchesNameOnly&lt;/code&gt; and &lt;code&gt;LaunchesAll&lt;/code&gt;. While specifying the &lt;code&gt;LaunchesAll&lt;/code&gt; query you can see how our environment helps us by indicating the type of &lt;code&gt;isBooked&lt;/code&gt;, that we are about to select. The type is a &lt;code&gt;Boolean!&lt;/code&gt;, a mandatory &lt;code&gt;Boolean&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In our next example we show how you hit the large &lt;code&gt;play&lt;/code&gt; button and is given the choice between different queries, as you can see it is a really great idea to define your queries with the keyword &lt;code&gt;query&lt;/code&gt; so to create some order in your testing environment:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QrPKn6by--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A3AobV3zHEwTwKOP7chtvBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QrPKn6by--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A3AobV3zHEwTwKOP7chtvBA.png" alt="" width="880" height="781"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is simply the result of executing our query&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kTyLf3LS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Ac9KDNGt2b_q8Oi_NhL137Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kTyLf3LS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Ac9KDNGt2b_q8Oi_NhL137Q.png" alt="" width="880" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s try to use variables next and see how we can declare those in the bottom left area and use them in our &lt;code&gt;queries&lt;/code&gt; and &lt;code&gt;mutations&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X6tB65_z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AWvXIYtoB8q2uYtun3ag6tA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X6tB65_z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AWvXIYtoB8q2uYtun3ag6tA.png" alt="" width="880" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above we have defined &lt;code&gt;OneLaunch&lt;/code&gt; that takes a parameter &lt;code&gt;$id&lt;/code&gt;. Thereafter this parameter &lt;code&gt;$id&lt;/code&gt; is passed down to our actual query expression like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;launch(id: $id) {
  mission {
    name
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we are ready to invoke our query, with a parameter and we simply hit the play button and we get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DHnyPyPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A_qAKfxncxFN9wl24BvManw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DHnyPyPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A_qAKfxncxFN9wl24BvManw.png" alt="" width="754" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason we get the above is that it read from the bottom left are that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mQo5Tamx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2ApKhKeGOIdkQG95B_tO5OiA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mQo5Tamx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2ApKhKeGOIdkQG95B_tO5OiA.png" alt="" width="880" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Variables in this area is all made up of one object and we simply add keys to this object when we need a new parameter like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "id": 1,
  "otherparam": "some value"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Deeper queries&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the big selling points of GraphQL is the ability to query deep into a hierarchy, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  orders {
    created,
    createdBy {
      name,
      created
    },
    items {
      product {
        name
      },
      price
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above we are querying on the resource &lt;code&gt;orders&lt;/code&gt; and as you can see we are able to perform a lot of subqueries and query for &lt;code&gt;orders-&amp;gt;items-&amp;gt;product&lt;/code&gt;. If we were to do that with SQL, it would be quite difficult with a lot of &lt;code&gt;JOINS&lt;/code&gt;. So how are we able to construct this in GraphQL?&lt;/p&gt;

&lt;p&gt;In short, we need to do two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;define&lt;/strong&gt; a resolver to the asked for subtype&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;store&lt;/strong&gt; the data in a &lt;em&gt;resolvable&lt;/em&gt; format. This means we need to store the data as an &lt;code&gt;id/ids&lt;/code&gt; rather than the full object&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Store the data as id/ids&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We need to store an order like this:&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;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Define a resolver for a subtype&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;How this is done syntactically depends on the GraphQL server implementation we are dealing with. In this case, we are dealing with Apollo, so let’s look at how Apollo handles it. We know that when we define a resolver object in Apollo it looks like this:&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="nl"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;orders&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;order&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// add mutation resolvers here&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;Now, our querying for &lt;code&gt;orders&lt;/code&gt; means we are interested in querying for all its columns like &lt;code&gt;created&lt;/code&gt; but also for a complex column like &lt;code&gt;items&lt;/code&gt; and even &lt;code&gt;items -&amp;gt; product&lt;/code&gt; so we can ask a query like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  orders {
    created,
    items {
      product {
        name
      },
      price
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So how do we resolve &lt;code&gt;items&lt;/code&gt;? Well let’s have a look at our schema definition of an order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Order {
  created: Date;
  items: [Item]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in mind let’s head back to our resolver object and now we will add a &lt;code&gt;Order&lt;/code&gt; type to like so:&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="nl"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;orders&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;order&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// add mutation resolvers here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&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;Let’s zoom into our addition:&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;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see that we are resolving what happens if someone queries for &lt;code&gt;items&lt;/code&gt;. We are missing the &lt;code&gt;getItems()&lt;/code&gt; method though so let’s define that:&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;itemsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="err"&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;item2&lt;/span&gt;&lt;span class="err"&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;getItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemsList&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;Ok, so that deals with &lt;code&gt;items&lt;/code&gt; so how do we deal with &lt;code&gt;items-&amp;gt;product&lt;/code&gt;. Well, that one is quite simple, we just again look at our schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type OrderItem {
  price: Double;
  product: Product;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see now that we need to add &lt;code&gt;OrderItem&lt;/code&gt; to our resolver object, like so:&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="nl"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;orders&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;order&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// add mutation resolvers here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;OrderItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have covered&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Installing&lt;/strong&gt; &lt;code&gt;apollo-server&lt;/code&gt; and &lt;code&gt;graphql&lt;/code&gt;, in order to have the necessary dependencies to create an apollo server.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Defined&lt;/strong&gt; a &lt;code&gt;schema&lt;/code&gt; and a set of &lt;code&gt;resolvers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Booted up our server&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Explored&lt;/strong&gt; the visual environment that allows us to run queries or mutations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moving on we will look at different ways to consume said server using &lt;code&gt;apollo-client&lt;/code&gt; so stay tuned for that.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>apollo</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Go from the beginning - your first program</title>
      <dc:creator>Chris Noring</dc:creator>
      <pubDate>Fri, 03 Jun 2022 13:55:33 +0000</pubDate>
      <link>https://dev.to/itnext/go-from-the-beginning-your-first-program-52n5</link>
      <guid>https://dev.to/itnext/go-from-the-beginning-your-first-program-52n5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;this is the first part of series on Go, the programming language, I hope it's helpful&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The language is called Go but is sometimes known as Golang as the first website for it was golang.org.&lt;/p&gt;

&lt;p&gt;Go was created in 2009 by Robert Griesemer, Rob Pike and Ken Thompson. It's hard to estimate the number of Go developers but it's somewhere between 1.1 and 2.7 million, quite a sizeable amount. More than 2500 companies are using Go including, Google, Pinterest and Uber. So you see, used by a lot of folks by big companies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why was Go created?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As is often the case, a programming language is created to deal with the shortcomings of other languages. In this case, the creators wanted this new language to have the following capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static typing&lt;/strong&gt; and run-time efficiency from C.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readability&lt;/strong&gt; from JavaScript and Python.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-performance&lt;/strong&gt; networking and multi-processing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems the creators agreed on disliking C++ :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it used for though?
&lt;/h2&gt;

&lt;p&gt;Here's some areas where you are likely to find a Go being used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud based and server-side apps&lt;/li&gt;
&lt;li&gt;DevOp, automation&lt;/li&gt;
&lt;li&gt;Command line tools&lt;/li&gt;
&lt;li&gt;AI and data science&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;There's many great resources out there for learning the Go programming language like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.dev/"&gt;https://go.dev/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/go/index.htm"&gt;https://www.tutorialspoint.com/go/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/"&gt;https://gobyexample.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/go/"&gt;https://www.w3schools.com/go/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/go-get-started/"&gt;https://docs.microsoft.com/en-us/learn/modules/go-get-started/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/serverless-go/"&gt;https://docs.microsoft.com/en-us/learn/modules/serverless-go/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;So what features makes Go compelling? Well, there are some features really worth mentioning that I personally appreciate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static typing&lt;/strong&gt;, I like my types :)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package system&lt;/strong&gt;. You can consume and create your own packages. Go to &lt;a href="https://pkg.go.dev/"&gt;pkg.go.dev&lt;/a&gt; to read more on what packages there are.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command line tools&lt;/strong&gt;, there's a set of executables that are installed when you install Go. With these executables, you can run, build, install packages, run tests and much more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard library&lt;/strong&gt;. Go has a powerful standard library that will help you with most things you might need. You can read more about what's in the &lt;a href="https://pkg.go.dev/std"&gt;standard library&lt;/a&gt; here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in testing&lt;/strong&gt;. Having a testing library that just works out of the box is something you shouldn't take for granted. &lt;/li&gt;
&lt;li&gt;Concurrency. Go is great at handling concurrency. It uses concepts like goroutines and channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collection&lt;/strong&gt;. You can read more about that &lt;a href="https://medium.com/safetycultureengineering/an-overview-of-memory-management-in-go-9a72ec7c76a8#:~:text=Go%20has%20all%20goroutines%20reach,the%20collector%20to%20run%20simultaneously"&gt;here&lt;/a&gt;. I like when I don't have to deal with that myself and just focusing on solving problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install Go
&lt;/h2&gt;

&lt;p&gt;Ok then, hope you are intrigued at this point and just want to see some code? Of course you are :)&lt;/p&gt;

&lt;p&gt;Make sure you've followed the instructions for installing Go on your machine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://go.dev/doc/install"&gt;https://go.dev/doc/install&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A Go program
&lt;/h2&gt;

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

&lt;p&gt;Here's what a first program can look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The program in detail
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;package main&lt;/code&gt;, the entry point module needs to have this instruction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import "fmt"&lt;/code&gt;, fmt is standard package for input and output.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;func main&lt;/code&gt;, entry point function, where your program starts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Now that you have a program, there's two things you might want to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run it&lt;/strong&gt;, to see if it compiles and runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create executable&lt;/strong&gt;, an executable is no longer Go code but like any executable program on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Run your app
&lt;/h3&gt;

&lt;p&gt;To run your app, type &lt;code&gt;go run &amp;lt;file&amp;gt;.go&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this produces an output looking like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build your app
&lt;/h3&gt;

&lt;p&gt;To produce an executable, run &lt;code&gt;go build &amp;lt;file&amp;gt;.go&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It produces an executable, on MacOS and Linux that's a file with -X as permission, on Windows, it's an .exe file.&lt;/p&gt;

&lt;p&gt;Congrats, you've created your first Go application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you learned about the programming language Go, some features it has and how to write your first program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;There are many great resources out there for learning the Go programming language like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.dev/"&gt;https://go.dev/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/go/index.htm"&gt;https://www.tutorialspoint.com/go/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/"&gt;https://gobyexample.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/go/"&gt;https://www.w3schools.com/go/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/go-get-started/"&gt;https://docs.microsoft.com/en-us/learn/modules/go-get-started/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/serverless-go/"&gt;https://docs.microsoft.com/en-us/learn/modules/serverless-go/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Instantly set up a new dev environment using containers and VS Code</title>
      <dc:creator>Yohan Lasorsa</dc:creator>
      <pubDate>Thu, 30 Sep 2021 15:00:11 +0000</pubDate>
      <link>https://dev.to/itnext/instantly-set-up-a-new-dev-environment-using-containers-and-vs-code-51g8</link>
      <guid>https://dev.to/itnext/instantly-set-up-a-new-dev-environment-using-containers-and-vs-code-51g8</guid>
      <description>&lt;p&gt;There are 3 things that make me waste a lot of time as a developer, and that can become a big source of frustration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up a new development machine&lt;/li&gt;
&lt;li&gt;Manage and update my development environment to work on a project&lt;/li&gt;
&lt;li&gt;Reinstall everything again, because after many times installing and updating my dev tools everything broke :(&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if I told you that we can avoid these issues, and that it's possible to perfectly isolate each of your projects' environment? And to be able to share and update it easily, to have nothing to do when a newcomer joins your project?&lt;/p&gt;

&lt;p&gt;It's now possible thanks to the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack&amp;amp;WT.mc_id=javascript-14373-yolasors" rel="noopener noreferrer"&gt;Remote Development extension&lt;/a&gt; for VS Code and containers. In this post, I'll show you how to set up a complete dev environment inside a container and use it with your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You can quickly onboard a new developer in a project using dev containers, share it with your teammates, and update it with no hassle.&lt;/li&gt;
&lt;li&gt;While nothing prevents you from using Docker and any IDE to do the same thing, the Remote Development extension provides seamless integration with VS Code to bootstrap and work with dev containers.&lt;/li&gt;
&lt;li&gt;Dev containers also allow you to take your dev environment everywhere with online dev tools like &lt;a href="https://github.com/features/codespaces" rel="noopener noreferrer"&gt;GitHub Codespaces&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why developing &lt;em&gt;inside&lt;/em&gt; a container
&lt;/h2&gt;

&lt;p&gt;In every software project, the developer story is (almost) always the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Hey, welcome to the team! We're all excited to have you on board!" 🎉&lt;/li&gt;
&lt;li&gt;"Here's the doc to set up your environment for the project. Let me know when you're ready!" (&lt;em&gt;spoiler alert:&lt;/em&gt; sometimes there's &lt;strong&gt;no doc&lt;/strong&gt; at all, and you'll have to ask your teammates to know what to install)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most likely, a few hours/days later, the outcome is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Please help, I can't figure out why it's still not building/running properly" 😞&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp3z7fvcqqq0fnvdzj9e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp3z7fvcqqq0fnvdzj9e.gif" alt="Animation showing developer saying " width="500" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've been that developer. A few times already.&lt;/p&gt;

&lt;p&gt;After a while of spending time reviewing everything you installed, you'll eventually discover common issues usually are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The environment setup doc is &lt;em&gt;outdated&lt;/em&gt; (I bet you didn't see that one coming, right? Isn't that the newcomer's job to update it anyway?).&lt;/li&gt;
&lt;li&gt;You installed the correct tools, but not the right &lt;em&gt;version&lt;/em&gt; ("Sorry, We forgot to tell you'll have to use this &lt;em&gt;specific version&lt;/em&gt;, as we have a few issues in our codebase").&lt;/li&gt;
&lt;li&gt;You have some &lt;em&gt;conflicts&lt;/em&gt; with the environment set up of other projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing is, we already know how to solve these problems, because that's the &lt;em&gt;exact same issues&lt;/em&gt; we had with production environments when we ship our applications.&lt;/p&gt;

&lt;p&gt;We solved all these problems by packaging the runtime environment of our applications into &lt;strong&gt;containers&lt;/strong&gt;. Then, why not also use containers for our &lt;em&gt;dev environment&lt;/em&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;You need to have these tools installed on your machine to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com?WT.mc_id=javascript-14373-yolasors" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; (or any Docker-compatible client)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack&amp;amp;WT.mc_id=javascript-14373-yolasors" rel="noopener noreferrer"&gt;Remote Development Extension for VS Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Open VS Code on a new or existing project, then click on the bottom left&lt;br&gt;
of the status bar, on the "opposing chevron" icon (let me know if you have a better name):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg0523a0hkhejmhp1ir7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg0523a0hkhejmhp1ir7.png" alt="Screenshot showing remote extension button in VS Code status bar" width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you do that, select &lt;strong&gt;Add Development Container Configuration Files...&lt;/strong&gt;, and it will open a huge list of environments starters. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu7w71xvmgg8zuku3no6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu7w71xvmgg8zuku3no6.png" alt="Screenshot showing remote extension" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll find pre-made configurations for Node.js, Java, .Net, Go, Python, and more, most likely there is one that you can use as a starting point. Once you've made your choice, you'll notice that a new &lt;code&gt;.devcontainer&lt;/code&gt; folder was created, containing 2 files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnhama6a2npzkkf3lguk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnhama6a2npzkkf3lguk.png" alt="Screenshot of the new folder in VS Code" width="344" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll dig into these files just after, for now, let's reload the project to work inside a container. &lt;/p&gt;

&lt;p&gt;Click again on that "opposing chevron" icon in the status bar, and select &lt;strong&gt;Reopen in container&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;VS Code will reload the project's window and start building the container. Depending on your internet connection speed, this may take a while but don't worry, it's only needed the first time.&lt;/p&gt;

&lt;p&gt;Once it's finished, you'll see that VS Code is connected to your dev container in the status bar. You can also open a terminal and play with your new dev environment (in my case, I've set up a new Node.js v14 environment).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6da23ph8fi9t1es78ii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6da23ph8fi9t1es78ii.png" alt="Screenshot of VS Code connected to a dev container with a terminal open" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Customizing the dev setup
&lt;/h2&gt;

&lt;p&gt;Now that you have a working environment, you'll probably want to customize it for your project's needs. If you unfold the &lt;code&gt;.devcontainer&lt;/code&gt; folder in the explorer, you'll see these 2 files that will allow you to do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;: this file defines your container configuration, and is used to build the container image that will be used for your environment. If you need to install additional tools or configure scripts and environment variables for your dev environment, this is where you should look at.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;: this file allows to customize VS Code when the project is connected to a development container. In particular, you can specify VS Code settings, extensions, and port forwarding that will be enabled only in this project dev container.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a deeper look at how you can fine-tune your VS Code dev environment by editing your &lt;code&gt;devcontainer.json&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;
  
  
  VS Code settings and overrides
&lt;/h3&gt;

&lt;p&gt;You'll see something like this under the &lt;code&gt;settings&lt;/code&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*default*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specific&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;settings.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;values&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;create.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.linux"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This key allows you to override any VS Code settings when it's connected to this container environment. For example, if you work on Windows and your default terminal is PowerShell, by connecting to the dev container the setting above with switch your default terminal to Bash instead, which will be run inside the Linux system of the dev container. With these settings, you can set a common code formatter for your team, or force GPG signing for your commits for example.&lt;/p&gt;

&lt;p&gt;Another useful option is located under the &lt;code&gt;extensions&lt;/code&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;IDs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;extension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;when&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;created.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"dbaeumeur.vscode-eslint"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one allows specifying extensions that will be automatically installed &lt;em&gt;within&lt;/em&gt; your dev container when it's run for the first time. Yes, you've read that well: these extensions won't pollute your global VS Code configuration, as they'll be available only when your dev container is started and connected to your project. No need to toggle your extensions anymore depending on your active project, no more having a useless C# extension active on your Java project!&lt;/p&gt;

&lt;p&gt;One last essential option, &lt;code&gt;forwardPorts&lt;/code&gt;, allows you to expose ports available from within your dev container and make them accessible by default from your local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'forwardPorts'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;inside&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;available&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;locally&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"forwardPorts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if you run a web server within your dev container, without port forwarding you won't be able to access it in your browser. Note that it's also possible to add ports to forward on the fly, by clicking on the antenna icon in the status bar, then selecting &lt;code&gt;Add Port&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwotdqj8cyrrok1h7p89v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwotdqj8cyrrok1h7p89v.png" alt="Screenshot of port forwarding panel in VS Code" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing and updating the environment
&lt;/h2&gt;

&lt;p&gt;Once your container and VS Code configuration is finished, you only have to push these two files in your repository to make them available for your team. And it's one of the big benefits of this approach! To welcome a new developer to your project, you now only have to clone the project, reload VS Code to use the container config and that's it. Take a coffee (or many) while the container is downloading and installing tools on its first run, and your new developer will have a dev environment ready for work, without any effort.&lt;/p&gt;

&lt;p&gt;Even better, if anyone updates the environment configuration, for example by upgrading a tool's version, everyone in the team will see this notification when pulling the changes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2bylpy6ldb0zpdvmt6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2bylpy6ldb0zpdvmt6g.png" alt="Screen showing the configuration changed dialog in VS Code" width="752" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You then only have to select &lt;code&gt;Rebuild&lt;/code&gt; to update your environment to the latest version. No more difficulties building a project when coming back from vacation!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where's the catch?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;It almost seems too good to be true, so where's the catch?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been asking that to myself since I started using it from the first beta, and so far it's been a happy ride. If you wonder about the performance, yes doing everything inside a container is a bit slower than doing it on the host machine, but nothing to worry about. In some cases, you may face disk performance issues especially with lots of small files (looking at you, &lt;code&gt;npm install&lt;/code&gt;) but there are tips to &lt;a href="https://code.visualstudio.com/remote/advancedcontainers/improve-performance?WT.mc_id=javascript-14373-yolasors" rel="noopener noreferrer"&gt;improve your filesystem performance with Docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The only issue I had at the beginning was with my git credentials as I'm using SSH keys, but once I've followed &lt;a href="https://code.visualstudio.com/docs/remote/containers?WT.mc_id=javascript-14373-yolasors#_sharing-git-credentials-with-your-container" rel="noopener noreferrer"&gt;the guide to set up an SSH agent&lt;/a&gt; everything went smoothly.&lt;/p&gt;

&lt;p&gt;You can have a look at the &lt;a href="https://code.visualstudio.com/docs/remote/containers?WT.mc_id=javascript-14373-yolasors#_known-limitations" rel="noopener noreferrer"&gt;known limitations&lt;/a&gt;, but so far I've yet to have any issue with it.&lt;/p&gt;

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

&lt;p&gt;This article is only a brief overview of what's possible with these tools, and of course, you can push it way further if needed, like creating a dev environment using multiple containers for example. You can have a look at &lt;a href="https://code.visualstudio.com/remote/advancedcontainers/overview?WT.mc_id=javascript-14373-yolasors" rel="noopener noreferrer"&gt;the documentation for more advanced scenarios&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going further, you could still argue that you have to install VS Code with the remote extension and a Docker-compatible runtime to make this work. It's also possible to get rid of that, using for example &lt;a href="https://github.com/features/codespaces" rel="noopener noreferrer"&gt;GitHub Codespace&lt;/a&gt; which makes use of the exact same tools and configuration to provide a cloud-based dev environment, accessible from any browser, without having to install anything (but a browser) on your machine.&lt;/p&gt;




&lt;p&gt;Follow me on &lt;a href="http://twitter.com/sinedied" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, I would be happy to discuss and take your suggestions!&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>tips</category>
    </item>
    <item>
      <title>Lazy Loading in Angular - A Beginner’s Guide</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Wed, 28 Apr 2021 07:17:00 +0000</pubDate>
      <link>https://dev.to/itnext/lazy-loading-in-angular-a-beginner-s-guide-57ln</link>
      <guid>https://dev.to/itnext/lazy-loading-in-angular-a-beginner-s-guide-57ln</guid>
      <description>&lt;h2&gt;What is Lazy Loading?&lt;/h2&gt;

&lt;p&gt;Lazy loading is a process of loading components, modules or other assets of a website as required. Since, Angular creates a &lt;a href="https://en.wikipedia.org/wiki/Single-page_application#:~:text=From%20Wikipedia%2C%20the%20free%20encyclopedia,browser%20loading%20entire%20new%20pages." rel="noreferrer noopener"&gt;SPA (Single Page Application)&lt;/a&gt;, all of its components are loaded, at once. Secondly, a lot of unnecessary libraries or modules might be loaded as well.&lt;/p&gt;

&lt;p&gt;For a small application it would be okay, but as the application grows the load time will increase, if everything is loaded at once. Lazy loading allows Angular to load components and modules as and when needed.&lt;/p&gt;

&lt;p&gt;First of all, to understand how lazy loading works in Angular, we need to understand the basic building blocks of the framework: NgModules.&lt;/p&gt;

&lt;p&gt;In order to understand how Lazy Loading works we first need to understand the building block of Angular: NgModules.&lt;/p&gt;

&lt;h2&gt;What are NgModules?&lt;/h2&gt;

&lt;p&gt;Angular libraries like RouterModule, BrowserModule, FormsModule are NgModules. Angular Material, which is a 3rd party, is also a type of NgModule. NgModule consists of files &amp;amp; code related to a specific domain or having a similar set of functionalities.&lt;/p&gt;

&lt;p&gt;A typical NgModule file declares components, directives, pipes, and services. It can also import other modules that are needed in the current module.&lt;/p&gt;

&lt;p&gt;One of the important advantage of NgModules is they can be lazy loaded.  Let's have a look at how we can configure lazy loading.&lt;/p&gt;

&lt;h2&gt;How to Create NgModules&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will create two modules &lt;em&gt;Module&lt;/em&gt; &lt;em&gt;A&lt;/em&gt; and &lt;em&gt;Module B&lt;/em&gt; which will be lazy loaded. On the main screen we will have two buttons for loading each module lazily.&lt;/p&gt;

&lt;h4&gt;Create a Project&lt;/h4&gt;

&lt;p&gt;Create a new Angular project &lt;em&gt;lazy-load-demo&lt;/em&gt; by executing the below command.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new lazy-load-demo --routing --strict --style css
code lazy-load-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are creating a new project with routing. Secondly, the &lt;a href="https://angular.io/guide/strict-mode" rel="noreferrer noopener"&gt;strict mode&lt;/a&gt; is enabled. Lastly, we are mentioning the stylesheet format to css. The second command opens your project in VS Code. &lt;/p&gt;

&lt;h4&gt;Root Module&lt;/h4&gt;

&lt;p&gt;By default, a root module or app module is created under &lt;em&gt;/src/app&lt;/em&gt;. Below is the NgModule file created:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we are importing all the required modules and components.&lt;/p&gt;

&lt;p&gt;After that, &lt;em&gt;&lt;strong&gt;@NgModule&lt;/strong&gt;&lt;/em&gt; decorator states that AppModule class is a type of NgModule. The decorator accepts &lt;em&gt;declarations, imports, providers, and bootstrap. &lt;/em&gt;Here are the descriptions for each of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;declarations&lt;/em&gt;&lt;/strong&gt;: The components in this module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;imports&lt;/em&gt;&lt;/strong&gt;: The modules that are required by the current module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;providers&lt;/em&gt;&lt;/strong&gt;: The service providers if any.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;bootstrap&lt;/em&gt;&lt;/strong&gt;: The &lt;em&gt;root&lt;/em&gt; component that Angular creates and inserts into the &lt;code&gt;index.html&lt;/code&gt; host web page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Main screen&lt;/h4&gt;

&lt;p&gt;The main screen will have 2 buttons, namely, &lt;strong&gt;&lt;em&gt;Load Module A &lt;/em&gt;&lt;/strong&gt;&amp;amp; &lt;strong&gt;&lt;em&gt;Load Module B.&lt;/em&gt;&lt;/strong&gt; As the name suggests, clicking these buttons will lazily load each module. &lt;/p&gt;

&lt;p&gt;For that, replace your &lt;em&gt;app.component.html&lt;/em&gt; file with the contents below:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button style="padding: 20px; color: white; background-color: green;" routerLink="a"&amp;gt;Load Module A&amp;lt;/button&amp;gt;
&amp;lt;button style="padding: 20px; color: white; background-color: blue;" routerLink="b"&amp;gt;Load Module B&amp;lt;/button&amp;gt;
&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's define the modules for routes &lt;em&gt;a &lt;/em&gt;&amp;amp; &lt;em&gt;b&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;Lazy Loaded Modules&lt;/h4&gt;

&lt;p&gt;In order to create lazy loaded modules execute the below commands.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate module modulea --route a --module app.module
ng generate module moduleb --route b --module app.module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands will generate two folders &lt;em&gt;&lt;strong&gt;modulea&lt;/strong&gt;&lt;/em&gt; &amp;amp; &lt;strong&gt;&lt;em&gt;moduleb&lt;/em&gt;&lt;/strong&gt;. Subsequently, each folder will contain their own &lt;em&gt;module.ts&lt;/em&gt;,&lt;em&gt; routing.ts &lt;/em&gt;and &lt;em&gt;component&lt;/em&gt; files.&lt;/p&gt;

&lt;p&gt;If you check your &lt;em&gt;app-routing.module.ts&lt;/em&gt; you will see the below code for routes.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const routes: Routes = [
  { path: 'a', loadChildren: () =&amp;gt; import('./modulea/modulea.module').then(m =&amp;gt; m.ModuleaModule) },
  { path: 'b', loadChildren: () =&amp;gt; import('./moduleb/moduleb.module').then(m =&amp;gt; m.ModulebModule) }
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It implies that when route &lt;em&gt;a&lt;/em&gt; or &lt;em&gt;b &lt;/em&gt;is visited load their respective modules lazily. &lt;/p&gt;

&lt;p&gt;On running the project with &lt;strong&gt;&lt;em&gt;ng serve&lt;/em&gt;&lt;/strong&gt;, you will see the below screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LIbbEMrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.18.55-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LIbbEMrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.18.55-PM.png" alt="" width="578" height="280"&gt;&lt;/a&gt;Home Page &lt;/p&gt;

&lt;p&gt;On clicking &lt;em&gt;Load Module A&lt;/em&gt; button, you will be routed to page &lt;em&gt;a&lt;/em&gt;. This is how your screen should look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1FzThyon--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.18.14-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1FzThyon--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.18.14-PM.png" alt="" width="644" height="326"&gt;&lt;/a&gt;Lazily loaded Module A&lt;/p&gt;

&lt;p&gt;You should see a similar screen that says &lt;strong&gt;&lt;em&gt;moduleb works! &lt;/em&gt;&lt;/strong&gt;when clicked on &lt;em&gt;Load Module B.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;How to Verify that the Lazy Loading Worked&lt;/h2&gt;

&lt;p&gt;In order to verify the files loaded, open the developer tools by pressing F12. After that, visit the &lt;em&gt;Network&lt;/em&gt; tab as you can see in the screenshot below. When you refresh the page it will show few files requested.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T5kLG29_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Network-Tab-1024x601.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T5kLG29_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Network-Tab-1024x601.jpg" alt="" width="880" height="516"&gt;&lt;/a&gt;Network Tab&lt;/p&gt;

&lt;p&gt;Go ahead and clear your list of requests by hitting the clear button as shown in the image on the right&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1OORoIBb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.42.21-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OORoIBb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.42.21-PM.png" alt="" width="320" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click on the &lt;em&gt;Load Module A&lt;/em&gt;, you will see a request for &lt;em&gt;modulea-modulea-module.js&lt;/em&gt; as in the screenshot below. This verifies that the &lt;em&gt;Module A &lt;/em&gt;was lazily loaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gd7g6C3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.46.50-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gd7g6C3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.46.50-PM.png" alt="" width="558" height="228"&gt;&lt;/a&gt;Module A Loaded&lt;/p&gt;

&lt;p&gt;Similarly, when you click &lt;em&gt;Load Module B&lt;/em&gt;, the &lt;em&gt;moduleb-moduleb-module.js&lt;/em&gt; file is loaded. Hence, verifying that Module B was loaded lazily.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6uMhJWXg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.47.10-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6uMhJWXg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/Screenshot-2021-04-25-at-11.47.10-PM.png" alt="" width="602" height="268"&gt;&lt;/a&gt;Module B Loaded&lt;/p&gt;

&lt;h2&gt;Use Cases&lt;/h2&gt;

&lt;p&gt;As we have seen, it’s very easy to create lazy loading modules. There are lots of use cases where they are useful, such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a separate module for pre-login vs post-login screens.&lt;/li&gt;
&lt;li&gt;For an e-commerce website, vendor facing vs customer facing screens can belong to separate modules. You can also create a separate module for payment.&lt;/li&gt;
&lt;li&gt;A separate CommonModule which contains shared components, directives, or pipelines is usually created. Directives like &lt;em&gt;Copy Code&lt;/em&gt; button, components like &lt;em&gt;up vote/down vote &lt;/em&gt;are usually included in a common module.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;For smaller websites, it might not matter much that all the modules are loaded at once. But, as the site grows it's very effective to have separate modules which are loaded as needed.&lt;/p&gt;

&lt;p&gt;Because of lazy loading, load time for the websites can be reduced drastically. This is specially helpful when you are trying to rank higher in SEO's. Even if not, less loading times means better user experience.&lt;/p&gt;

&lt;p&gt;Are you interested in more articles? Check these out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/learn-test-driven-development-with-integration-tests-in-net-5-0"&gt;Learn TDD with Integration Tests in .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/net-5-how-to-authenticate-authorise-api-s-correctly"&gt;How to authenticate &amp;amp; authorise API’s correctly in .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/azure-functions-wkhtmltopdf-convert-html-to-pdf"&gt;Azure Functions &amp;amp; wkhtmltopdf: Convert HTML to PDF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>performance</category>
    </item>
    <item>
      <title>5 Ways to Increase Your Efficiency as a Developer</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Thu, 22 Apr 2021 13:38:00 +0000</pubDate>
      <link>https://dev.to/itnext/5-ways-to-increase-your-efficiency-as-a-developer-265e</link>
      <guid>https://dev.to/itnext/5-ways-to-increase-your-efficiency-as-a-developer-265e</guid>
      <description>&lt;p&gt;Like any other field, the efficiency of a developer varies based on several factors: work culture, management, personal life, skills, and so on. Some we can control, and some we cannot.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss how to make oneself better by working on things we control. There are some clichéd tips like &lt;em&gt;Stay Focused, Avoid Distractions &lt;/em&gt;and&lt;em&gt; Be in the FLOW&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But we are going to get a bit more technical on increasing the efficiency.&lt;/p&gt;

&lt;h2&gt;Journey of a Software Developer&lt;/h2&gt;

&lt;p&gt;The usual stages of a developer are shown below:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Coder -&amp;gt; Programmer -&amp;gt; Architect&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Coder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many people use the words “coder” and “programmer” interchangeably. But, there is a difference between the two. A coder is someone who knows how to write the code or a script. Optimisation and architecture are not their priority. Rather, they focus on writing code that just works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Programmer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A programmer is a superset of a coder. They know how to write code, but in addition, they also write it with great optimisation and robustness. Secondly, time and memory complexities are kept in mind when writing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architect&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As you might have guessed, the architect or the software architect, to be precise, is a superset of a programmer. The architect is responsible for not only a piece of code but also how these pieces fit together.&lt;/p&gt;

&lt;h2&gt;Coder vs. Programmer vs. Architect: An Example&lt;/h2&gt;

&lt;p&gt;A great example would be to ask these three people to “Create tic-tac-toe.”&lt;/p&gt;

&lt;p&gt;When asking the coders, they will start coding, assuming it's a 3x3 tic-tac-toe with two players. Secondly, they might write nested &lt;em&gt;for &lt;/em&gt;loops as a brute force approach to figure out who won the match. There might also be no design patterns in place like MVC, MVVM, or others.&lt;/p&gt;

&lt;p&gt;However, the programmer will first understand the requirements completely and then start on the coding part. They will create optimised algorithms for maintaining the state of the players and a scalable way to change the grid dimensions.&lt;/p&gt;

&lt;p&gt;The architect will select which technology is best for designing the game. A few other questions come into play: Is it going to be a web-based or mobile app? Will an API be required or just played locally? In addition, they will also decide on which design patterns to implement. Once the architecture is defined, only then will the actual implementation start.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The goal of each developer should be to become a great architect along with having great technical skills.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Here are a few ways to improve your efficiency and skills:&lt;/p&gt;

&lt;h2&gt;1. Pen and Paper&lt;/h2&gt;

&lt;p&gt;Many people find it offensive to give a pen and paper coding interview. In my opinion, it is one of the best tools to get clarity. Jot down the things that you want to achieve and how you will achieve them.&lt;/p&gt;

&lt;p&gt;In the tic-tac-toe example above, you can write down that there will be models like Player and Board. Secondly, a game engine will be required to calculate the result after each move. Also, write down what each class will contain, e.g., Player will have a name and symbol property.&lt;/p&gt;

&lt;p&gt;You get the idea. Figure out your design patterns. What you are trying to achieve in code, achieve it with pen and paper first.&lt;/p&gt;

&lt;h2&gt;2. Become Your Own Manager&lt;/h2&gt;

&lt;p&gt;At the start of the day, create a TODO list of your tasks, e.g., you will complete the game engine today, or you will complete the board UI today, etc.&lt;/p&gt;

&lt;p&gt;Try to break it down into smaller tasks of 3–4 hours each. Having clear goals for the day keeps you motivated. Secondly, it gives a sense of satisfaction when the tasks are completed; it boosts morale.&lt;/p&gt;

&lt;p&gt;Essentially, it’s a variant of the &lt;a href="https://www.atlassian.com/agile/kanban#:~:text=Kanban%20is%20a%20popular%20framework,of%20work%20at%20any%20time." rel="noopener noreferrer"&gt;Kanban&lt;/a&gt; management style. But, I have found it to be quite effective.&lt;/p&gt;

&lt;h2&gt;3. Documentation&lt;/h2&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%2Fmiro.medium.com%2Fmax%2F1400%2F0%2Aic31iXHxVYtLUjWo.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%2Fmiro.medium.com%2Fmax%2F1400%2F0%2Aic31iXHxVYtLUjWo.png" alt=""&gt;&lt;/a&gt;&lt;em&gt;&lt;span&gt;Reference: &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/ijoxq6/why_read_documentation/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/ProgrammerHumor/comments/ijoxq6/why_read_documentation/&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the reasons for taking time to get things right is a lack of knowledge.&lt;/p&gt;

&lt;p&gt;Astonishingly, there are many developers who just assume how the system or library works. They spend an enormous amount of time figuring out by themselves how it works without reading the documentation. This leads to a loss in efficiency.&lt;/p&gt;

&lt;p&gt;A simple example I personally encountered was writing blogs using the Markdown syntax. I know most of the basic syntax, but I was unaware of some of the advanced ones. I wasted around 5–10 minutes trying to figure it out. If I had gone to the documentation, instead, it would have saved me time.&lt;/p&gt;

&lt;p&gt;Here is a &lt;a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Here-Cheatsheet" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; cheat sheet in case you are wondering.&lt;/p&gt;

&lt;h2&gt;4. Don’t Reinvent the Wheel&lt;/h2&gt;

&lt;p&gt;If something is already available in the market, with great reliability, use it. Usually speaking the pros will outweigh the cons.&lt;/p&gt;

&lt;p&gt;As an example, you should never write your own cryptographic function or library. There are pretty decent libraries available in almost all languages, and they will save you lots of time. More importantly, it will have the correct implementation, and it will be well optimised&lt;/p&gt;

&lt;p&gt;But don’t overdo it. You shouldn’t import &lt;a href="https://underscorejs.org/" rel="noopener noreferrer"&gt;underscore&lt;/a&gt; or &lt;a href="https://lodash.com/" rel="noopener noreferrer"&gt;lodash&lt;/a&gt; just to loop through an array. It only increases your package size and hurts the user experience.&lt;/p&gt;

&lt;h2&gt;5. Testing&lt;/h2&gt;

&lt;p&gt;Test-Driven Development (TDD) is another methodology that is going strong. Writing tests is as important as writing code. Though manual testing is required, automated tests provide confidence that your system will not break logically.&lt;/p&gt;

&lt;p&gt;Initially, it might feel that you are spending more time writing tests. But as the project grows, it would be worth it. Fewer bugs and more robustness.&lt;/p&gt;

&lt;p&gt;Here is an article on &lt;a href="https://www.daveops.co.in/post/learn-test-driven-development-with-integration-tests-in-net-5-0" rel="noopener noreferrer"&gt;how to do TDD&lt;/a&gt; in .NET Core.&lt;/p&gt;

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

&lt;p&gt;I, personally, felt a lot of different emotions when following the above tips, but they have improved my efficiency a lot, especially creating a to-do list for the day.&lt;/p&gt;

&lt;p&gt;Read more interesting articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/xcode-vs-android-studio-which-is-worse" rel="noopener noreferrer"&gt;XCode or Android Studio: Which is Better?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/continuous-integration-ci-cd-for-ios-part-1" rel="noopener noreferrer"&gt;Setup CI-CD for iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/how-to-setup-ci-cd-pipelines-for-android-with-azure-devops" rel="noopener noreferrer"&gt;Setup CI-CD for Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.daveops.co.in/post/learn-test-driven-development-with-integration-tests-in-net-5-0" rel="noopener noreferrer"&gt;Learning Integration Tests in .NET with .TDD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devjournal</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>XCode vs Android Studio: Which is better?</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Tue, 20 Apr 2021 05:04:44 +0000</pubDate>
      <link>https://dev.to/itnext/xcode-vs-android-studio-which-is-worse-251m</link>
      <guid>https://dev.to/itnext/xcode-vs-android-studio-which-is-worse-251m</guid>
      <description>&lt;h2&gt;What makes me eligible to review!&lt;/h2&gt;

&lt;p&gt;I have been in the industry for more than 11+ years now. I started my career with BlackBerry (BB) Development. I feel old already!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Eclipse&lt;/em&gt;&lt;/strong&gt; was our best friend back then for mobile development. I did my internship working on the famous &lt;a href="https://zagat.com/" rel="noreferrer noopener"&gt;Zagat&lt;/a&gt; app for BlackBerry. It was overall a great learning experience.&lt;/p&gt;

&lt;p&gt;For my full-time job I switched to a start up named &lt;a href="https://www.linkedin.com/company/spinlet/" rel="noreferrer noopener"&gt;Spinlet&lt;/a&gt; which I hope is still going strong. I worked as BlackBerry developer in the beginning but switched to iOS development eventually.&lt;/p&gt;

&lt;p&gt;My iOS experience was nothing but exciting in those initial years. Eventually I started my own firm &lt;a href="https://royalecheese.com" rel="noreferrer noopener"&gt;Royale Cheese&lt;/a&gt; with a friend that provides mobile design &amp;amp; development. &lt;/p&gt;

&lt;p&gt;After around 4 years of iOS development I found my way into Android development. I have got a fair share of experience with Android development as well, around 3 years to be precise.&lt;/p&gt;

&lt;p&gt;We have since then been working on full stack. That's when I realised how horrible the mobile development tools are.&lt;/p&gt;

&lt;p&gt;Enough with the chit chat. Here's an honest review of the mobile development tools and technologies. &lt;/p&gt;

&lt;h2&gt;XCode&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---MUSt2J7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/xcode.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---MUSt2J7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/xcode.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It used to be a good tool in the past. But it has become terrible lately. Here is a list of all the issues even after 15 years:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-completion&lt;/strong&gt;: Firstly, who in the right mind would set Esc as the suggestions key. Secondly, the autocompletion doesn't work many a times or gives weird suggestions that are out of context. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Times&lt;/strong&gt;: It takes a lot of time to create an archive or to run on a device for the first time. It's best to &lt;a href="https://arjavdave.com/2021/03/11/continuous-integration-cicd-for-ios-on-azure-devops-part-1/" rel="noreferrer noopener"&gt;setup a CI/CD&lt;/a&gt; to archive and upload builds. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signing &amp;amp; Deployment:&lt;/strong&gt; With the latest version's it's getting easier. But, it's still confusing with the signing certificates and the provision profiles for someone who is a beginner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Hog&lt;/strong&gt;: Somehow XCode keeps on hogging memory. For every new device on which the build needs to run it occupies 3 GB. Archives take a huge chunk and so as the simulators. Overall it occupies around 50GB if I don't clean up regularly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updates&lt;/strong&gt;: Each update is around 10-12GB even the minor upgrades. What's worse is it requires more than 40GB of free space to get installed. Last but not the least, XCode takes around 12GB of the space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design&lt;/strong&gt;: Initially to design UI there was struts &amp;amp; springs, then came the Autolayout and now the SwiftUI. It is worrisome that the methodology keeps on changing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cocoapods&lt;/strong&gt;: is getting worse day by day because it's repo is getting so big. Secondly, it increases the build times by a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Camera&lt;/strong&gt;: Possibly due to hardware limitations camera was not supported in simulators. But, now it's been a while. If the location can be simulated why not the Camera?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Android Studio&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MaYra0EV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/android-studio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MaYra0EV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://arjavdave.com/wp-content/uploads/2021/04/android-studio.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven't got the chance to use it in the early days. But from what I have been seeing it wouldn't have been pretty. Here are some of the frustrating issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fragmentation&lt;/strong&gt;: I feel this might be on top of every ones list. Supporting the staggering amount of devices to support might just overwhelm anyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradle&lt;/strong&gt;: Oh My God! Gradle takes forever to run builds. There are optimisation's which can help alleviate the problem, but it still remains the problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM Hogger&lt;/strong&gt;: With emulators and IDE running together, the combo requires around 10-12GB of RAM. That's way more than what their official documentation says: &lt;strong&gt;&lt;em&gt;4GB&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signing Keys&lt;/strong&gt;: You lose your signing keys and you can't upload to the same app again. You will have to create a new app and get the reviews and downloads again. There is some improvement in this area recently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IDE: &lt;/strong&gt;I always felt Java based IDE's to be clumsy. That includes IntelliJ (on which Android Studio is based), Eclipse or NetBeans. It's responsiveness is not like other tools like XCode or VS Code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;XCode vs Android Studio Review&lt;/h2&gt;

&lt;p&gt;Even though it might feel Android has less issues it does have some serious issues. &lt;strong&gt;Fragmentation&lt;/strong&gt; and &lt;strong&gt;Gradle&lt;/strong&gt; might alone be enough to make Android look bad. &lt;/p&gt;

&lt;p&gt;Personally I prefer to work in XCode compared to Android since I own a Mac and probably I am more used to it. &lt;/p&gt;

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

&lt;p&gt;Overall both platforms have a huge user base. But, I feel that these tools still have a long way to go. &lt;/p&gt;

&lt;p&gt;As an example I am absolutely in love how Microsoft has revamped dotnet to &lt;a href="https://dotnet.microsoft.com/download" rel="noreferrer noopener"&gt;dotnet core&lt;/a&gt; and their IDE to &lt;a href="https://code.visualstudio.com/" rel="noreferrer noopener"&gt;VS Code&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Jot down your frustrations in the comments below. &lt;/p&gt;

&lt;p&gt;Read some of my articles here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arjavdave.com/2021/03/11/continuous-integration-cicd-for-ios-on-azure-devops-part-1/" rel="noreferrer noopener"&gt;Setup CI-CD for iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arjavdave.com/2021/03/16/how-to-setup-ci-cd-pipelines-for-android-with-azure-devops/" rel="noreferrer noopener"&gt;Setup CI-CD for Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arjavdave.com/2021/04/14/learn-test-driven-development-with-integration-tests-in-net-5-0/" rel="noreferrer noopener"&gt;Learning Integration Tests in .NET with .TDD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arjavdave.com/2021/04/05/going-password-less-with-dotnet/" rel="noreferrer noopener"&gt;Provide a password-less to login&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>discuss</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Learn Test-Driven Development with Integration Tests in .NET 5.0</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Wed, 14 Apr 2021 18:00:20 +0000</pubDate>
      <link>https://dev.to/itnext/learn-tdd-with-integration-tests-in-net-5-0-31fg</link>
      <guid>https://dev.to/itnext/learn-tdd-with-integration-tests-in-net-5-0-31fg</guid>
      <description>&lt;p&gt;TDD (Test Driven Development) is a much debated word in the tech industry. Debates like &lt;em&gt;Whether you should do TDD or not?&lt;/em&gt; or &lt;em&gt;How advantageous is it?&lt;/em&gt;  are quite popular. Simply said, TDD is write tests before you develop. &lt;/p&gt;

&lt;p&gt;Now, there are a lot of school of thoughts regarding what type of test's are included and what are not in TDD. As an example, should it include Unit Test, Integration Test, System Test or even UAT? &lt;/p&gt;

&lt;p&gt;In this article, we will go through a real-world example on how to write integration tests in .NET 5.0 with TDD methodology.&lt;/p&gt;

&lt;h2&gt;Project Requirements&lt;/h2&gt;

&lt;p&gt;TDD requires a very clear understanding of scope of work. Without clarity, all the test cases might not be covered.&lt;/p&gt;

&lt;p&gt;Let's define the scope of work. We will be developing a &lt;em&gt;patient admission system&lt;/em&gt; for a Hospital.&lt;/p&gt;

&lt;h4&gt;Business Requirements&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A hospital has X ICU rooms, Y Premium rooms &amp;amp; Z General rooms.&lt;/li&gt;
&lt;li&gt;ICU &amp;amp; Premium rooms can have a single patient at a time, while General rooms can have 2 patients. Each room has a room number.&lt;/li&gt;
&lt;li&gt;On admitting, the patient has to provide name, age, gender &amp;amp; phone number. &lt;/li&gt;
&lt;li&gt;It is possible to search a patient via name or phone number.&lt;/li&gt;
&lt;li&gt;Same patient cannot be admitted to multiple beds while he is still checked in.&lt;/li&gt;
&lt;li&gt;A patient cannot be admitted if all the rooms are occupied.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Model Validation Rules&lt;/h4&gt;

&lt;p&gt;Based on the above requirements, there are 2 models namely Patient &amp;amp; Room. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A patient's age is between 0 &amp;amp; 150. The length of name should be between 2 and 40. Gender can be male, female &amp;amp; other. Phone Number's length should be between 7 and 12 and it should all be digits. &lt;/li&gt;
&lt;li&gt;Room type can be either "ICU", "Premium" or "General".&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Test Cases&lt;/h4&gt;

&lt;p&gt;Now, that we have defined rules &amp;amp; requirements, lets start creating test cases. Since it's a basic CRUD application we mostly have integration tests. &lt;/p&gt;

&lt;h6&gt;Patient&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Do all the model validation tests.&lt;/li&gt;
&lt;li&gt;Admit the same patient twice&lt;/li&gt;
&lt;li&gt;Check out the same patient twice. &lt;/li&gt;
&lt;li&gt;Admit the same patient to multiple rooms at the same time.&lt;/li&gt;
&lt;li&gt;Search a patient with phone number and name.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In the above section we gathered requirements. Secondly, we defined the models. Finally, we created the list of test cases which we will implement. &lt;/p&gt;

&lt;p&gt;Open your terminal and run the below script to create and setup a new project.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir TDD
cd TDD
dotnet new sln
dotnet new webapi --name TDD
dotnet new xunit --name TDD.Tests
cd TDD
dotnet add package Microsoft.EntityFrameworkCore --version 5.0.5
cd ../TDD.Tests
dotnet add reference ../TDD/TDD.csproj
dotnet add package Microsoft.EntityFrameworkCore --version 5.0.5
dotnet add package Microsoft.AspNetCore.Hosting --version 2.2.7
dotnet add package Microsoft.AspNetCore.Mvc.Testing --version 5.0.5
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 5.0.5
cd ..
dotnet sln add TDD/TDD.csproj
dotnet sln add TDD.Tests/TDD.Tests.csproj
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above script creates a solution file named &lt;em&gt;TDD.sln&lt;/em&gt;. Secondly, we create 2 projects for TDD &amp;amp; TDD.Tests. Then we add the dependencies for each project. Lastly, we add the projects to the solution and open the project in VS Code. &lt;/p&gt;

&lt;p&gt;Before we start testing, some more setup is required. Basically, integration tests test the a specific module without mocking. So we will be mimicking our application via TestServer.&lt;/p&gt;

&lt;h4&gt;Custom WAF&lt;/h4&gt;

&lt;p&gt;In order to mimic the TestServer there is a class called &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.testing.webapplicationfactory-1?view=aspnetcore-5.0" rel="noreferrer noopener"&gt;WebApplicationFactory&lt;/a&gt; (WAF) which bootstraps the application in memory.&lt;/p&gt;

&lt;p&gt;In your &lt;strong&gt;&lt;em&gt;TDD.Tests&lt;/em&gt;&lt;/strong&gt; project create a file named &lt;em&gt;PatientTestsDbWAF.cs&lt;/em&gt; with the following code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore;


namespace TDD.Tests
{
    public class PatientTestsDbWAF&amp;lt;TStartup&amp;gt; : WebApplicationFactory&amp;lt;TStartup&amp;gt; where TStartup : class
    {

        protected override IWebHostBuilder CreateWebHostBuilder()
        {
            return WebHost.CreateDefaultBuilder()
                .UseStartup&amp;lt;TStartup&amp;gt;();
        }
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(async services =&amp;gt;
           {
               // Remove the app's DbContext registration.
               var descriptor = services.SingleOrDefault(
                      d =&amp;gt; d.ServiceType ==
                          typeof(DbContextOptions&amp;lt;DataContext&amp;gt;));

               if (descriptor != null)
               {
                   services.Remove(descriptor);
               }

               // Add DbContext using an in-memory database for testing.
               services.AddDbContext&amp;lt;DataContext&amp;gt;(options =&amp;gt;
                  {
                      // Use in memory db to not interfere with the original db.
                      options.UseInMemoryDatabase("PatientTestsTDD.db");
                  });
           });
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are removing the applications DbContext and adding an &lt;strong&gt;in memory&lt;/strong&gt; DbContext. It is a necessary step since we don't want to interfere with the original database. &lt;/p&gt;

&lt;p&gt;Secondly, we are initialising the database with some dummy data. &lt;/p&gt;

&lt;p&gt;Since, DataContext is a custom class, it will give compiler error. So, we need to create it.&lt;/p&gt;

&lt;h4&gt;Data Context&lt;/h4&gt;

&lt;p&gt;Therefore, in your &lt;strong&gt;TDD project&lt;/strong&gt;, create a file named &lt;em&gt;DataContext.cs&lt;/em&gt; with the following code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore;

namespace TDD
{
    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions options) : base(options) { }

        // For storing the list of patients and their state
        public DbSet&amp;lt;Patient&amp;gt; Patient { get; set; }

        // For the storying the rooms along with their types and capacity
        public DbSet&amp;lt;Room&amp;gt; Room { get; set; }

        // For logging which patients are currently admitted to which room
        public DbSet&amp;lt;RoomPatient&amp;gt; RoomPatient { get; set; }

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

&lt;/div&gt;



&lt;p&gt;Here Patient, Room &amp;amp; RoomPatient are Entity classes with the required properties, which we will create next.&lt;/p&gt;

&lt;h4&gt;Patient&lt;/h4&gt;

&lt;p&gt;Again, in your &lt;strong&gt;TDD project&lt;/strong&gt;, create a file named &lt;em&gt;Patient.cs&lt;/em&gt; and paste in the code below.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public class Patient
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public String Name { get; set; }

        public String PhoneNumber { get; set; }

        public int Age { get; set; }

        public String Gender { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;Room&lt;/h4&gt;

&lt;p&gt;Create another file named &lt;em&gt;Room.cs&lt;/em&gt; with the following code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public class Room
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public String RoomType { get; set; }

        public int CurrentCapacity { get; set; }

        public int MaxCapacity { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;RoomPatient&lt;/h4&gt;

&lt;p&gt;Create the last model file &lt;em&gt;RoomPatient.cs&lt;/em&gt; with the following code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public class RoomPatient
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        public int RoomId { get; set; }

        [ForeignKey("RoomId")]
        public Room Room { get; set; }

        [Required]
        public int PatientId { get; set; }

        [ForeignKey("PatientId")]
        public Patient Patient { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you shouldn't be getting any compiler error.&lt;/p&gt;

&lt;p&gt;Lastly, remove the WeatherForecast.cs and WeatherForecastController.cs files. &lt;/p&gt;

&lt;p&gt;Go to your terminal in VS Code and run the below command.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd TDD.Tests
dotnet test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see a nice green result which says 1 test passed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2FTest_Success_1-1024x211.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%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2FTest_Success_1-1024x211.png" alt=""&gt;&lt;/a&gt;Test Success&lt;/p&gt;

&lt;h4&gt;Patient Controller&lt;/h4&gt;

&lt;p&gt;Unfortunately dotnet doesn't provide a way to directly test the model's in itself. So, we will have to create a controller to test it. &lt;/p&gt;

&lt;p&gt;Go ahead and create &lt;em&gt;PatientController.cs&lt;/em&gt; in the Controllers folder in &lt;strong&gt;TDD project&lt;/strong&gt; with the below code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Mvc;

namespace TDD.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PatientController : Controller
    {
        [HttpPost]
        public IActionResult AddPatient([FromBody] Patient Patient)
        {
            // TODO: Insert the patient into db
            return Created("/patient/1", Patient);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created an api to add a patient. In order to test our model we will call this api.&lt;/p&gt;

&lt;p&gt;That is all the things required to start testing.&lt;/p&gt;

&lt;h2&gt;Model Validation Tests&lt;/h2&gt;

&lt;p&gt;Since, we have setup the basic code for testing, let's write a test that fails. We will start our testing with the model validation tests.&lt;/p&gt;

&lt;h4&gt;Failing (Red) State&lt;/h4&gt;

&lt;p&gt;Let's create a new file named &lt;em&gt;PatientTests.cs&lt;/em&gt; in your &lt;strong&gt;TDD.Tests project&lt;/strong&gt; and delete the file named &lt;em&gt;UnitTest1.cs&lt;/em&gt;. Copy the below code in your file.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace TDD.Tests
{
    public class PatientTests : IClassFixture&amp;lt;PatientTestsDbWAF&amp;lt;Startup&amp;gt;&amp;gt;
    {
        // HttpClient to call our api's
        private readonly HttpClient httpClient;
        public WebApplicationFactory&amp;lt;Startup&amp;gt; _factory;

        public PatientTests(PatientTestsDbWAF&amp;lt;Startup&amp;gt; factory)
        {
            _factory = factory;

            // Initiate the HttpClient
            httpClient = _factory.CreateClient();
        }

        [Theory]
        [InlineData("Test Name 2", "1234567891", 20, "Male", HttpStatusCode.Created)]
        [InlineData("T", "1234567891", 20, "Male", HttpStatusCode.BadRequest)]
        [InlineData("A very very very very very very loooooooooong name", "1234567891", 20, "Male", HttpStatusCode.BadRequest)]
        [InlineData(null, "1234567890", 20, "Invalid Gender", HttpStatusCode.BadRequest)]
        [InlineData("Test Name", "InvalidNumber", 20, "Male", HttpStatusCode.BadRequest)]
        [InlineData("Test Name", "1234567890", -10, "Male", HttpStatusCode.BadRequest)]
        [InlineData("Test Name", "1234567890", 20, "Invalid Gender", HttpStatusCode.BadRequest)]
        [InlineData("Test Name", "12345678901234444", 20, "Invalid Gender", HttpStatusCode.BadRequest)]
        public async Task PatientTestsAsync(String Name, String PhoneNumber, int Age, String Gender, HttpStatusCode ResponseCode)
        {
            var scopeFactory = _factory.Services;
            using (var scope = scopeFactory.CreateScope())
            {
                var context = scope.ServiceProvider.GetService&amp;lt;DataContext&amp;gt;();

                // Initialize the database, so that 
                // changes made by other tests are reset. 
                await DBUtilities.InitializeDbForTestsAsync(context);

                // Arrange
                var request = new HttpRequestMessage(HttpMethod.Post, "api/patient");

                request.Content = new StringContent(JsonSerializer.Serialize(new Patient
                {
                    Name = Name,
                    PhoneNumber = PhoneNumber,
                    Age = Age,
                    Gender = Gender
                }), Encoding.UTF8, "application/json");

                // Act
                var response = await httpClient.SendAsync(request);

                // Assert
                var StatusCode = response.StatusCode;
                Assert.Equal(ResponseCode, StatusCode);
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[Theory] attribute allows us to mention different parameters for our tests. Consequently, we don't have to write different tests for all the combinations.&lt;/p&gt;

&lt;p&gt;Also, DBUtilities is a utility class to reinitialise the database to it's initial state. This might seem trivial when we have 1 or 2 tests but, gets critical as we add more tests. &lt;/p&gt;

&lt;h4&gt;DBUtilities&lt;/h4&gt;

&lt;p&gt;The DBUtilities class will initialise your database with 1 patient and 3 different type of rooms. &lt;/p&gt;

&lt;p&gt;Create a file named &lt;em&gt;DBUtilities.cs&lt;/em&gt; in your &lt;strong&gt;&lt;em&gt;TDD.Tests&lt;/em&gt;&lt;/strong&gt; project with the below code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Threading.Tasks;

namespace TDD.Tests
{
    // Helps to initialise the database either from the WAF for the first time
    // Or before running each test.
    public class DBUtilities
    {

        // Clears the database and then,
        //Adds 1 Patient and 3 different types of rooms to the database
        public static async Task InitializeDbForTestsAsync(DataContext context)
        {
            context.RoomPatient.RemoveRange(context.RoomPatient);
            context.Patient.RemoveRange(context.Patient);
            context.Room.RemoveRange(context.Room);

            // Arrange
            var Patient = new Patient
            {
                Name = "Test Patient",
                PhoneNumber = "1234567890",
                Age = 20,
                Gender = "Male"
            };
            context.Patient.Add(Patient);

            var ICURoom = new Room
            {
                RoomType = "ICU",
                MaxCapacity = 1,
                CurrentCapacity = 1
            };
            context.Room.Add(ICURoom);

            var GeneralRoom = new Room
            {
                RoomType = "General",
                MaxCapacity = 2,
                CurrentCapacity = 2
            };
            context.Room.Add(GeneralRoom);

            var PremiumRoom = new Room
            {
                RoomType = "Premium",
                MaxCapacity = 1,
                CurrentCapacity = 1
            };
            context.Room.Add(PremiumRoom);

            await context.SaveChangesAsync();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go ahead and run the &lt;em&gt;dotnet test&lt;/em&gt; command again and you will see 1 passed and 4 failed tests. This is because the 4 tests were expecting BadRequest but getting a Created result. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2Ffailed_tests-1024x195.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%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2Ffailed_tests-1024x195.png" alt=""&gt;&lt;/a&gt;Failing (Red) State&lt;/p&gt;

&lt;p&gt;Let's fix it!&lt;/p&gt;

&lt;h4&gt;Success (Green) State&lt;/h4&gt;

&lt;p&gt;In order to fix these we need to add attributes to our &lt;em&gt;Patient.cs&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;Update the &lt;em&gt;Patient.cs&lt;/em&gt; file as below.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TDD
{
    public class Patient : IValidatableObject
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        [StringLength(40, MinimumLength = 2, ErrorMessage = "The name should be between 2 &amp;amp; 40 characters.")]
        public String Name { get; set; }

        [Required]
        [DataType(DataType.PhoneNumber)]
        [RegularExpression(@"^(\d{7,12})$", ErrorMessage = "Not a valid phone number")]
        public String PhoneNumber { get; set; }

        [Required]
        [Range(1, 150)]
        public int Age { get; set; }

        [Required]
        public String Gender { get; set; }

        public Boolean IsAdmitted { get; set; }

        public IEnumerable&amp;lt;ValidationResult&amp;gt; Validate(ValidationContext validationContext)
        {
            // Only Male, Female or Other gender are allowed
            if (Gender.Equals("Male", System.StringComparison.CurrentCultureIgnoreCase) == false &amp;amp;&amp;amp;
                Gender.Equals("Female", System.StringComparison.CurrentCultureIgnoreCase) == false &amp;amp;&amp;amp;
                Gender.Equals("Other", System.StringComparison.CurrentCultureIgnoreCase) == false)
            {
                yield return new ValidationResult("The gender can either be Male, Female or Other");
            }

            yield return ValidationResult.Success;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we have added the required attributes. We have also implemented the &lt;em&gt;IValidatableObject&lt;/em&gt; interface so that we can verify the &lt;em&gt;Gender&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Time to run the &lt;em&gt;dotnet test&lt;/em&gt; command. You will see a nice green line saying 5 tests passed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2FTests_passed_2-1024x244.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%2Farjavdave.com%2Fwp-content%2Fuploads%2F2021%2F04%2FTests_passed_2-1024x244.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can add more edge case scenarios in the &lt;em&gt;InlineData&lt;/em&gt; to test the Patient model validation tests thoroughly.&lt;/p&gt;

&lt;h2&gt;Duplicate Patient Test&lt;/h2&gt;

&lt;p&gt;We shall now create a test which fails when we try to add a duplicate patient.&lt;/p&gt;

&lt;h4&gt;Failing (Red) Test&lt;/h4&gt;

&lt;p&gt;Create another test in your class &lt;em&gt;PatientTests. &lt;/em&gt;Add the below code.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Fact]
public async Task PatientDuplicationTestsAsync()
{
    var scopeFactory = _factory.Services;
    using (var scope = scopeFactory.CreateScope())
    {
        var context = scope.ServiceProvider.GetService&amp;lt;DataContext&amp;gt;();
        await DBUtilities.InitializeDbForTestsAsync(context);

        // Arrange
        var Patient = await context.Patient.FirstOrDefaultAsync();

        var Request = new HttpRequestMessage(HttpMethod.Post, "api/patient");
        Request.Content = new StringContent(JsonSerializer.Serialize(Patient), Encoding.UTF8, "application/json");

        // Act
        var Response = await httpClient.SendAsync(Request);

        // Assert
        var StatusCode = Response.StatusCode;
        Assert.Equal(HttpStatusCode.BadRequest, StatusCode);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have used a [Fact] attribute instead of [Theory] attribute here since we don't want to test the same method with different parameters. Instead, we want to make the same request twice.&lt;/p&gt;

&lt;p&gt;Run &lt;em&gt;&lt;strong&gt;dotnet test &lt;/strong&gt;&lt;/em&gt;to run our newly created test. The test will fail with message &lt;em&gt;Assert.Equal() Failure&lt;/em&gt;. Time to fix it.&lt;/p&gt;

&lt;h4&gt;Success (Green) Test&lt;/h4&gt;

&lt;p&gt;To fix the failing test we need to add the implementation for the AddPatient method in &lt;em&gt;PatientController.cs&lt;/em&gt;. Update the file's code as below.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace TDD.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PatientController : Controller
    {
        private readonly DataContext _context;

        public PatientController(DataContext context)
        {
            _context = context;
        }
        [HttpPost]
        public async Task&amp;lt;IActionResult&amp;gt; AddPatientAsync([FromBody] Patient Patient)
        {
            var FetchedPatient = await _context.Patient.FirstOrDefaultAsync(x =&amp;gt; x.PhoneNumber == Patient.PhoneNumber);
            // If the patient doesn't exist create a new one
            if (FetchedPatient == null)
            {
                _context.Patient.Add(Patient);
                await _context.SaveChangesAsync();
                return Created($"/patient/{Patient.Id}", Patient);
            }
            // Else throw a bad request
            else
            {
                return BadRequest();
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the &lt;strong&gt;&lt;em&gt;dotnet test &lt;/em&gt;&lt;/strong&gt;again and you will see that the test has passed.&lt;/p&gt;

&lt;p&gt;You can run all the tests by calling &lt;strong&gt;&lt;em&gt;dotnet test.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Important Notes&lt;/h2&gt;

&lt;p&gt;As you add more models/domains like Doctors, Staff, Instruments etc. You will have to create more tests. Make sure to have a different WAF, utility wrappers and different Test files for each of them.&lt;/p&gt;

&lt;p&gt;Secondly, the tests in the same file do not run in parallel. But, the tests from different files do run in parallel. Therefore, each WAF should have a different database name so that data is not misconfigured. &lt;/p&gt;

&lt;p&gt;Lastly, the connections to the original database still needs to be setup in the main project. &lt;/p&gt;

&lt;h2&gt;Thought Process&lt;/h2&gt;

&lt;p&gt;The thought process for creating tests for all scenarios are similar. &lt;/p&gt;

&lt;p&gt;That is, you should first identify the requirements. Then, set up a skeleton of methods and classes without implementation. Write tests to verify the implementation. Finally, refactor as needed and rerun the tests.&lt;/p&gt;

&lt;p&gt;This tutorial didn't include authentication and authorisation for api's. You can &lt;a href="https://arjavdave.com/2021/03/31/net-5-setup-authentication-and-authorisation/" rel="noreferrer noopener"&gt;read here&lt;/a&gt; on how to set it up.&lt;/p&gt;

&lt;p&gt;Since, it is not possible to cover all the test cases, I have created a &lt;a href="https://github.com/shenanigan/tdd-demo" rel="noreferrer noopener"&gt;repository on Github&lt;/a&gt;. It covers the implementation for all the test cases and the implementation as well. &lt;/p&gt;

&lt;p&gt;You can find the &lt;a href="https://github.com/shenanigan/tdd-demo" rel="noreferrer noopener"&gt;project here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In order for TDD to be effective you really need to have a clear idea of what the requirements are. If the requirements keep on changing it would get very tough to maintain the tests as well as the project. &lt;/p&gt;

&lt;p&gt;TDD mainly covers unit, integration &amp;amp; functional tests. You will still have to do UAT, Configuration &amp;amp; Production testing before you go live. &lt;/p&gt;

&lt;p&gt;Having said that, TDD is really helpful in making your project bug free. Secondly, it boosts your confidence for the implementation. You will be able to change bits &amp;amp; pieces of your code as long as the tests pass. Lastly, it provides a better architecture for your project. &lt;/p&gt;

&lt;p&gt;Hope you like the article. Let me know your thoughts or feedback. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://arjavdave.com" rel="noopener noreferrer"&gt;Check more tutorials on .NET here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Just let me login! Going Password less with .NET</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Tue, 06 Apr 2021 06:40:00 +0000</pubDate>
      <link>https://dev.to/itnext/just-let-me-login-going-password-less-with-net-24i6</link>
      <guid>https://dev.to/itnext/just-let-me-login-going-password-less-with-net-24i6</guid>
      <description>&lt;h2&gt;
  
  
  Passwords are a pain in the a..
&lt;/h2&gt;

&lt;p&gt;With thousand's of softwares and app's launching everyday, you would like to make your software stand out. Most importantly, it should have some unique USP, but in addition it should provide convenience and ease of use. &lt;/p&gt;

&lt;p&gt;For instance, one of the pain points for many apps is they require a username and a password to login. I personally have to remember 10-15 passwords for apps like Gmail, Facebook, Instagram, etc. You get the idea. &lt;/p&gt;

&lt;p&gt;In today's article we are going to create a solution for your API's that will allow your users to login without a password.&lt;/p&gt;

&lt;h2&gt;
  
  
  The How of Going Password less
&lt;/h2&gt;

&lt;p&gt;In order to omit the password there needs to be some type of token generated for a user. &lt;/p&gt;

&lt;p&gt;This token will then be sent to a user where only the user can access it e.g. on email or phone number. Here is an overview of the flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eu-DInEa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njjypscirkr5stsiqexu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eu-DInEa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njjypscirkr5stsiqexu.png" alt="No Password Login Flow" width="880" height="502"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Dotnet Identity provides ways to generate tokens for email confirmation or changing email or phone. We will see more about it below.&lt;/p&gt;

&lt;p&gt;There are mainly two token providers available&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TotpSecurityStampBasedTokenProvider (Time-based One Time Password).&lt;/li&gt;
&lt;li&gt;DataProtectionTokenProvider&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  TotpSecurityStampBasedTokenProvider
&lt;/h4&gt;

&lt;p&gt;It generates time based tokens which are valid for around 3 minutes (Reference: &lt;a href="https://github.com/aspnet/AspNetIdentity/blob/b7826741279450c58b230ece98bd04b4815beabf/src/Microsoft.AspNet.Identity.Core/Rfc6238AuthenticationService.cs#L75"&gt;Source Code&lt;/a&gt;). Based on the token provider the tokens are generated from the Email, PhoneNumber or user's id as well as the user's security stamp. &lt;/p&gt;

&lt;p&gt;Dotnet Identity provides utility classes EmailTokenProvider and PhoneNumberTokenProvider that are subclasses of TotpSecurityStampBasedTokenProvider.&lt;/p&gt;

&lt;h4&gt;
  
  
  DataProtectorTokenProvider
&lt;/h4&gt;

&lt;p&gt;If you want to generate a token that doesn't expire for a long duration DataProtectorTokenProvider is the way to go. &lt;/p&gt;

&lt;p&gt;DataProtectorTokenProvider generates tokens using a DataProtector and cryptographic algorithms. You can check out the implementation for more details &lt;a href="https://github.com/aspnet/AspNetIdentity/blob/main/src/Microsoft.AspNet.Identity.Owin/DataProtectorTokenProvider.cs"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article we are going to subclass &lt;em&gt;DataProtectorTokenProvider&lt;/em&gt; so that our token is valid for 10 minutes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Identity
&lt;/h2&gt;

&lt;p&gt;The .NET Identity provides ways to manage users, passwords, profile data, roles, claims, tokens, email confirmation, and more. &lt;/p&gt;

&lt;p&gt;Let's start with a scratch project. Create a new project by executing the command &lt;strong&gt;dotnet new webapi –-name NoPasswordProject&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 5.0.4
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore --version 5.0.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to create an in memory database for this tutorial. But you can use a database of your choice and accordingly change the package above. &lt;/p&gt;

&lt;p&gt;Note: The in memory database will clear the users every time the server restarts. &lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Token Provider
&lt;/h2&gt;

&lt;p&gt;Let's create a custom token provider that generates token that are valid for 10 minutes.&lt;/p&gt;

&lt;h4&gt;
  
  
  NPTokenProvider
&lt;/h4&gt;

&lt;p&gt;Create a new file called NPTokenProvider.cs. NP prefix stands for No Password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

public class NPTokenProvider&amp;lt;TUser&amp;gt; : DataProtectorTokenProvider&amp;lt;TUser&amp;gt;
where TUser : IdentityUser
{
    public NPTokenProvider(
        IDataProtectionProvider dataProtectionProvider,
        IOptions&amp;lt;NPTokenProviderOptions&amp;gt; options, ILogger&amp;lt;NPTokenProvider&amp;lt;TUser&amp;gt;&amp;gt; logger)
        : base(dataProtectionProvider, options, logger)
    { }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are here subclassing the DataProtectorTokenProvider. Nothing out of the ordinary except in the constructor we are passing NPTokenProviderOptions. The options need to be subclass of DataProtectionTokenProviderOptions.&lt;/p&gt;

&lt;h4&gt;
  
  
  NPTokenProviderOptions
&lt;/h4&gt;

&lt;p&gt;Create a new file NPTokenProviderOptions.cs and paste in the below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using Microsoft.AspNetCore.Identity;

public class NPTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public NPTokenProviderOptions()
    {
        Name = "NPTokenProvider";
        TokenLifespan = TimeSpan.FromMinutes(10);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are setting options for the tokens to be created. You can change the Name and TokenLifeSpan to your liking. &lt;/p&gt;

&lt;h4&gt;
  
  
  DbContext
&lt;/h4&gt;

&lt;p&gt;Almost every project needs database to store it's users and other data related to the project. Dotnet EF Framework provides a nice helper &lt;em&gt;DbContext&lt;/em&gt; to handle sessions with the database and query and save entites. So create a subclass of &lt;em&gt;IdentityDbContext&lt;/em&gt; which is in turn a subclass of &lt;em&gt;DbContext&lt;/em&gt;. Name the file &lt;em&gt;NPDataContext.cs&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

public class NPDataContext : IdentityDbContext
{
    public NPDataContext(DbContextOptions&amp;lt;NPDataContext&amp;gt; options)
        : base(options)
    { }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Startup.cs
&lt;/h4&gt;

&lt;p&gt;We have created the classes; now time to configure them in our &lt;em&gt;Startup.cs&lt;/em&gt; files. In &lt;em&gt;ConfigureServices&lt;/em&gt; add the below code at the start.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = services
.AddIdentityCore&amp;lt;IdentityUser&amp;gt;()
.AddEntityFrameworkStores&amp;lt;NPDataContext&amp;gt;();

var UserType = builder.UserType;
var provider = typeof(NPTokenProvider&amp;lt;&amp;gt;).MakeGenericType(UserType);
builder.AddTokenProvider("NPTokenProvider", provider);

services.AddDbContext&amp;lt;NPDataContext&amp;gt;(options =&amp;gt;
    options.UseInMemoryDatabase(Guid.NewGuid().ToString()));

services.AddAuthentication(options =&amp;gt;
{
    options.DefaultScheme = IdentityConstants.ExternalScheme;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also add &lt;strong&gt;app.UseAuthentication();&lt;/strong&gt; above &lt;em&gt;app.UseAuthorization();&lt;/em&gt; in &lt;em&gt;Configure&lt;/em&gt; method.&lt;/p&gt;

&lt;h4&gt;
  
  
  NoPasswordController.cs
&lt;/h4&gt;

&lt;p&gt;Let's create a controller for our login and verify API's. Create a &lt;em&gt;NoPasswordController.cs&lt;/em&gt; file in your &lt;em&gt;Controllers&lt;/em&gt; folder. Add the below content to the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace NoPasswordProject.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class NoPasswordController : ControllerBase
    {
        private readonly UserManager&amp;lt;IdentityUser&amp;gt; _userManager;

        public NoPasswordController(UserManager&amp;lt;IdentityUser&amp;gt; userManager)
        {
            _userManager = userManager;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are injecting an instance of UserManager in our controller. UserManager is used for CRUD operations for a user as well as generating tokens and validating it. &lt;/p&gt;

&lt;h4&gt;
  
  
  Login API
&lt;/h4&gt;

&lt;p&gt;Let's add a &lt;em&gt;Login&lt;/em&gt; api which accepts an Email as input. The Email is the unique identifier for a user i.e. there should be a one-to-one relation ship between user and email.&lt;/p&gt;

&lt;p&gt;Create a new function in your controller as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpGet]
public async Task&amp;lt;ActionResult&amp;lt;String&amp;gt;&amp;gt; Login([FromQuery] string Email)
{
    // Create or Fetch your user from the database
    var User = await _userManager.FindByNameAsync(Email);
    if (User == null)
    {
        User = new IdentityUser();
        User.Email = Email;
        User.UserName = Email;
        var IdentityResult = await _userManager.CreateAsync(User);
        if (IdentityResult.Succeeded == false)
        {
            return BadRequest();
        }
    }

    var Token = await _userManager.GenerateUserTokenAsync(User, "NPTokenProvider", "nopassword-for-the-win");

    // DON'T RETURN THE TOKEN.
    // SEND IT TO THE USER VIA EMAIL.
    return NoContent();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are fetching a User from the database. If the user doesn't exist then we create a user. Make sure to set the UserName as well or it will give runtime error.&lt;/p&gt;

&lt;p&gt;Then based on the user, we generate a UserToken. The &lt;em&gt;GenerateUserTokenAsync&lt;/em&gt; takes the user, token provider and the purpose for generating a token. &lt;/p&gt;

&lt;p&gt;The token provider string should be the one you have used in &lt;em&gt;NPTokenProviderOptions&lt;/em&gt;. The purpose can be anything you want.&lt;/p&gt;

&lt;p&gt;Send out the token to the user via a link in a nicely designed email. When the user will click on the link in the email it will open your front-end page. Consequently this page will request the Verify api.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verify API
&lt;/h4&gt;

&lt;p&gt;Let's add another api &lt;em&gt;Verify&lt;/em&gt; that takes the &lt;em&gt;Email&lt;/em&gt; and &lt;em&gt;Token&lt;/em&gt; as query parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpGet]
public async Task&amp;lt;ActionResult&amp;lt;String&amp;gt;&amp;gt; Verify([FromQuery] string Token, [FromQuery] string Email)
{
    // Fetch your user from the database
    var User = await _userManager.FindByNameAsync(Email);
    if (User == null)
    {
        return NotFound();
    }

    var IsValid = await _userManager.VerifyUserTokenAsync(User, "NPTokenProvider", "nopassword-for-the-win", Token);
    if (IsValid)
    {
        // TODO: Generate a bearer token
        var BearerToken = "";
        return BearerToken;
    }
    return Unauthorized();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are again fetching the user based on email. As a result if we are not able to find the user return 404 Not Found. &lt;/p&gt;

&lt;p&gt;We then continue to verify the user. &lt;em&gt;VerifyUserTokenAsync&lt;/em&gt; takes user, token provider, purpose and token as input parameters. The purpose should be same as the one used while generating token. &lt;/p&gt;

&lt;p&gt;If the token is not valid, return 401 Unauthorised. Otherwise return the bearer token. &lt;a href="https://www.daveops.co.in/post/net-5-how-to-authenticate-authorise-api-s-correctly"&gt;This is a good article&lt;/a&gt; on how to generate bearer token for the user.&lt;/p&gt;

&lt;p&gt;In conclusion our article explains on how to allow users to login without a password. You can find the whole project &lt;a href="https://github.com/shenanigan/dotnet-passwordless"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Providing features was supposed to be the most important thing in the '90s. But today besides having great features, the convenience for the users is a priority.&lt;/p&gt;

&lt;p&gt;We looked at one of the ways of providing convenience. That said, let us know in the comments below for more ways to do it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://daveops.co.in"&gt;Check here&lt;/a&gt; for more tutorials like this.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>security</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>.NET 5: How to authenticate &amp; authorise API's correctly</title>
      <dc:creator>Arjav Dave</dc:creator>
      <pubDate>Thu, 01 Apr 2021 05:21:53 +0000</pubDate>
      <link>https://dev.to/itnext/net-5-how-to-authenticate-authorise-api-s-correctly-4db8</link>
      <guid>https://dev.to/itnext/net-5-how-to-authenticate-authorise-api-s-correctly-4db8</guid>
      <description>&lt;p&gt;In over 11 years of my experience I have seen so many API's that have major security flaw. They either lack a proper setup of Authentication or Authorisation or both. The developers might feel okay since these endpoints are usually not public. But it is a huge security loop hole which anyone can easily target. &lt;/p&gt;

&lt;p&gt;To better understand security for API's let's create a demo project for FBI. There will be an Admin who can enrol FBI Agents and change their clearance levels. Secondly FBI Agents with &lt;em&gt;Clearance Level 1&lt;/em&gt; will be able to access public files and agents with &lt;em&gt;Clearance Level 2&lt;/em&gt; will be able to access pubic &amp;amp; classified files.&lt;/p&gt;

&lt;p&gt;First some theory! Not Interested? Take me to the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;Our Agent has successfully cleared all his exams; time to enrol him. In order to do that he will provide his documents and in return will get his badge. &lt;/p&gt;

&lt;p&gt;In the above scenario &lt;em&gt;providing documents&lt;/em&gt; is like login where once verified he will be provided with a token (badge). This process is called &lt;em&gt;Authentication&lt;/em&gt;. It determines whether agents are who they claim to be. &lt;/p&gt;

&lt;p&gt;We are going to use Json Web Tokens (JWT) Bearer tokens for authentication. &lt;em&gt;Bearer tokens&lt;/em&gt; are a type of tokens generated by servers which contain details of the claims/roles of a user trying to login. Bearer tokens are mostly structured tokens like &lt;em&gt;JWT&lt;/em&gt;. &lt;a href="https://jwt.io/introduction" rel="noopener noreferrer"&gt;Read here&lt;/a&gt; to know more about JWT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorisation
&lt;/h2&gt;

&lt;p&gt;Now since the FBI Agent has got his badge he can enter the FBI building. He is also able to access public files, but when trying to access classified files he gets &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401" rel="noopener noreferrer"&gt;401&lt;/a&gt;&lt;/em&gt; error. &lt;/p&gt;

&lt;p&gt;This is because FBI Agent is not &lt;em&gt;authorised&lt;/em&gt; to access classified files. &lt;em&gt;Authorisation&lt;/em&gt; determines what agents can and cannot access.&lt;/p&gt;

&lt;p&gt;As mentioned above the JWT Bearer token contains claims/roles. Based on it, our server decides whether to give access to a private resource or not. &lt;/p&gt;

&lt;h2&gt;
  
  
  Access Flow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1pcf6w2cjhtj9hgzm8v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1pcf6w2cjhtj9hgzm8v.jpg" alt="Access Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the above diagram on successful login the server returns a Bearer token. The client uses the bearer token in subsequent calls to access a private resource. &lt;/p&gt;

&lt;p&gt;These are the two main concepts that we are going to implement in our article. &lt;/p&gt;

&lt;p&gt;Enough with the theory, show me some code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Create a new project by executing the command &lt;strong&gt;dotnet new webapi --name FBI&lt;/strong&gt; from your cli. It will create a project with a sample WeatherForecast api. &lt;/p&gt;

&lt;p&gt;Why work on WeatherForecast when we can work on FBI. Go ahead and delete &lt;em&gt;WeatherForecast.cs&lt;/em&gt; file. &lt;/p&gt;

&lt;p&gt;Add dependencies by executing the commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.IdentityModel.Tokens --version 6.9.0
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 5.0.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;ConfigureServices&lt;/em&gt; function in your &lt;em&gt;Startup.cs&lt;/em&gt; file add the below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var TokenValidationParameters = new TokenValidationParameters
{
    ValidIssuer = "https://fbi-demo.com",
    ValidAudience = "https://fbi-demo.com",
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SXkSqsKyNUyvGbnHs7ke2NCq8zQzNLW7mPmHbnZZ")),
    ClockSkew = TimeSpan.Zero // remove delay of token when expire
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are defining the parameters for validating a token. Make sure that the length of the string for generating SymmetricSecurityKey is 32.&lt;/p&gt;

&lt;p&gt;Next, setup the services to add authentication for API's.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services
    .AddAuthentication(options =&amp;gt;
    {
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(cfg =&amp;gt;
    {
        cfg.TokenValidationParameters = TokenValidationParameters;
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;AddAuthentication&lt;/em&gt; method registers services required by authentication services. It also configures JWT Bearer Authentication as the default scheme.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;AddJwtBearer&lt;/em&gt; enables JWT-bearer authentication and setting the TokenValidationParameters defined above.&lt;/p&gt;

&lt;p&gt;Now let's add some Authorisation claims for our &lt;em&gt;Agent&lt;/em&gt; &amp;amp; &lt;em&gt;Admin&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddAuthorization(cfg =&amp;gt;
    {
        cfg.AddPolicy("Admin", policy =&amp;gt; policy.RequireClaim("type", "Admin"));
        cfg.AddPolicy("Agent", policy =&amp;gt; policy.RequireClaim("type", "Agent"));
        cfg.AddPolicy("ClearanceLevel1", policy =&amp;gt; policy.RequireClaim("ClearanceLevel", "1", "2"));
        cfg.AddPolicy("ClearanceLevel2", policy =&amp;gt; policy.RequireClaim("ClearanceLevel", "2"));
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;AddAuthorization&lt;/em&gt; method registers services required for authorisation. We are also adding claims for &lt;em&gt;Admin&lt;/em&gt;, &lt;em&gt;Agent&lt;/em&gt;, &lt;em&gt;ClearanceLevel1&lt;/em&gt; and &lt;em&gt;ClearanceLevel2&lt;/em&gt; by calling &lt;em&gt;AddPolicy&lt;/em&gt;. A claim is a name value pair that represents what the subject is. Since clearance level 2 can also access clearance level 1 we have put &lt;em&gt;"1", "2"&lt;/em&gt; in ClearanceLevel1. You can read more about claims &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims?view=aspnetcore-5.0" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lastly in the &lt;em&gt;Configure&lt;/em&gt; method add the below line just above &lt;em&gt;app.UseAuthorization();&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseAuthentication();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Admin Controller
&lt;/h2&gt;

&lt;p&gt;Rename your file &lt;em&gt;WeatherForecastController.cs&lt;/em&gt; to &lt;em&gt;AdminController.cs&lt;/em&gt;. Do change the class name and constructor names as well. Finally, remove everything except the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Mvc;

namespace FBI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class AdminController : ControllerBase
    {
        public AdminController() { }
    }
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Login API
&lt;/h3&gt;

&lt;p&gt;Let's create a login API for Admin so that she can get a token to perform other tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpPost]
[Route("[action]")]
public IActionResult Login([FromBody] User User)
{
    // TODO: Authenticate Admin with Database
    // If not authenticate return 401 Unauthorized
    // Else continue with below flow

    var Claims = new List&amp;lt;Claim&amp;gt;
            {
                new Claim("type", "Admin"),
            };

    var Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SXkSqsKyNUyvGbnHs7ke2NCq8zQzNLW7mPmHbnZZ"));

    var Token = new JwtSecurityToken(
        "https://fbi-demo.com",
        "https://fbi-demo.com",
        Claims,
        expires: DateTime.Now.AddDays(30.0),
        signingCredentials: new SigningCredentials(Key, SecurityAlgorithms.HmacSha256)
    );

    return new OkObjectResult(new JwtSecurityTokenHandler().WriteToken(Token));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code &lt;em&gt;User&lt;/em&gt; is a model with properties &lt;em&gt;Username&lt;/em&gt; &amp;amp; &lt;em&gt;Password&lt;/em&gt;. We are also creating an object of &lt;em&gt;JwtSecurityToken&lt;/em&gt; using configurations that we have used in &lt;em&gt;Startup.cs&lt;/em&gt; file. The token is then converted to string and returned in an OkObjectResult.&lt;/p&gt;

&lt;p&gt;You can now open Swagger and execute the API to see a bearer token. A bearer token will be returned as you can see below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faedozuzics30gunpp3b5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faedozuzics30gunpp3b5.png" alt="Bearer Token Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep the token handy since we are going to use it in the next section. You can also visit &lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;https://jwt.io&lt;/a&gt; to analyse your token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate Badge API
&lt;/h3&gt;

&lt;p&gt;Generating badge for an Agent is a sensitive task and should only be Authorised by an &lt;em&gt;Admin&lt;/em&gt;. We are going to add an &lt;em&gt;Authorize&lt;/em&gt; attribute for the &lt;em&gt;GenerateBadge&lt;/em&gt; api.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpPost]
[Route("[action]")]
[Authorize(Policy = "Admin")]
public IActionResult GenerateBadge([FromBody] Agent Agent)
{
    var Claims = new List&amp;lt;Claim&amp;gt;
    {
        new Claim("type", "Agent"),
        new Claim("ClearanceLevel", Agent.ClearanceLevel.ToString()),
    };

    var Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SXkSqsKyNUyvGbnHs7ke2NCq8zQzNLW7mPmHbnZZ"));

    var Token = new JwtSecurityToken(
        "https://fbi-demo.com",
        "https://fbi-demo.com",
        Claims,
        expires: DateTime.Now.AddDays(30.0),
        signingCredentials: new SigningCredentials(Key, SecurityAlgorithms.HmacSha256)
    );

    return new OkObjectResult(new JwtSecurityTokenHandler().WriteToken(Token));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here Agent is a model with properties &lt;em&gt;Name&lt;/em&gt; as string and &lt;em&gt;ClearanceLevel&lt;/em&gt; as int.&lt;/p&gt;

&lt;p&gt;Now when you go back to swagger and try to execute &lt;em&gt;GenerateBadge&lt;/em&gt; api it will give you 401 Unauthorised response. Since we have not passed the bearer token we are getting this error. &lt;/p&gt;

&lt;p&gt;To be able to add the Authorize header in Swagger change the &lt;em&gt;services.AddSwaggerGen&lt;/em&gt; as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddSwaggerGen(c =&amp;gt;
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "FBI", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        In = ParameterLocation.Header,
        Description = "Please enter JWT with Bearer into field",
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement {
    { new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer"}
            },
        new string[] {}
    }
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you refresh Swagger in your browser you will notice an &lt;em&gt;Authorize&lt;/em&gt; button on the right side above the list of apis.&lt;/p&gt;

&lt;p&gt;Click on the newly added &lt;em&gt;Authorize&lt;/em&gt; button in Swagger which will open up a dialog. We need to mention what type of token it is. So first enter &lt;em&gt;Bearer&lt;/em&gt; in the field then a space and then the token generated from the &lt;em&gt;/Admin/Login&lt;/em&gt; api from previous section. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ks0jtoy39ogcpa61s71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ks0jtoy39ogcpa61s71.png" alt="Authorization Header"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the header to lock in the token. Now you are all set. When you execute the &lt;em&gt;GenerateBadge&lt;/em&gt; api again you will get a token (analogous to badge). Keep this token handy, since we require in next section. Also make sure to &lt;strong&gt;pass ClearanceLevel as 1&lt;/strong&gt; for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Controller
&lt;/h2&gt;

&lt;p&gt;Create a new file &lt;em&gt;AgentController.cs&lt;/em&gt; with below content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Mvc;

namespace FBI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    [Authorize(Policy = "Agent")]
    public class AgentController : ControllerBase
    {
        public AgentController() { }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see above we are authorising the whole controller for Agent's access only. So even Admin won't be able to access the API's we are going to create.&lt;/p&gt;

&lt;h3&gt;
  
  
  Access Records API's
&lt;/h3&gt;

&lt;p&gt;Let's add the api's to access both public and classified files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpGet]
[Route("[action]")]
[Authorize(Policy = "ClearanceLevel1")]
public ActionResult&amp;lt;String&amp;gt; AccessPublicFiles()
{
    return new OkObjectResult("Public Files Accessed");
}

[HttpGet]
[Route("[action]")]
[Authorize(Policy = "ClearanceLevel2")]
public ActionResult&amp;lt;String&amp;gt; AccessClassifiedFiles()
{
    return new OkObjectResult("Classified Files Accessed");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have added &lt;em&gt;Authorize&lt;/em&gt; attribute's for both API's such that public files can be accessed by &lt;em&gt;ClearanceLevel1&lt;/em&gt; and classified files can be accessed by &lt;em&gt;ClearanceLevel2&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you try to access these API's with the Admin token you will get 403 Forbidden error. So go ahead and click on the &lt;em&gt;Authorize&lt;/em&gt; button again and click on &lt;em&gt;logout&lt;/em&gt;. Then, get the token from the above step and paste in the field with &lt;em&gt;Bearer&lt;/em&gt; as a prefix i.e. &lt;em&gt;Bearer &lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Now when you access &lt;em&gt;/Agent/AccessPublicFiles&lt;/em&gt; api you will see response 200 with message &lt;em&gt;Public Files Accessed&lt;/em&gt;. But when you try the classified api you get 403 Forbidden error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changing Clearance Level
&lt;/h2&gt;

&lt;p&gt;Fast forward 3 years and our &lt;em&gt;Agent's&lt;/em&gt; performance has been mind bogglingly good. Management has now decided to promote him to ClearanceLevel2. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Agent&lt;/em&gt; goes to the &lt;em&gt;Admin&lt;/em&gt; and asks her to provide a token/badge with Clearance Level 2.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Admin&lt;/em&gt; calls the &lt;em&gt;/Admin/Login&lt;/em&gt; api to generate his own token first. She then enters it in the &lt;em&gt;Authorize&lt;/em&gt; dialog. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;/Admin/GenerageBadge&lt;/em&gt; api is then called by Admin with value 2 in the ClearanceLevel. This generates a new token/badge which she then hands over to &lt;em&gt;Agent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Agent&lt;/em&gt; enters this token/badge in the &lt;em&gt;Authorize&lt;/em&gt; dialog and when he now calls &lt;em&gt;/Agent/AccessClassifiedFiles&lt;/em&gt; he is pleased to see the result &lt;em&gt;Classified Files Accessed&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;You can find the whole project &lt;a href="https://github.com/shenanigan/fbi-demo" rel="noopener noreferrer"&gt;here&lt;/a&gt; on github.&lt;/p&gt;

&lt;p&gt;API security is extremely important and shouldn't be taken lightly even if it's for internal use only. Setup Authentication and Authorisation and you are halfway there. &lt;/p&gt;

&lt;p&gt;There are other other security measures you can security against DDoS attacks, accepting API's from a particular IP or domain only etc.&lt;/p&gt;

&lt;p&gt;How did you like the article? What are the other security measures do you usually take? Any feedbacks or comments?&lt;/p&gt;

&lt;p&gt;You can checkout out more tutorials &lt;a href="https://arjavdave.com" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>dotnet</category>
      <category>cybersecurity</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
