Web

Technologies 2021

{
  "name": "Alexandru Păvăloi",
  "nickname": "Păvă",
  "age": 26,
  "labPage": "iampava.com/web-technologies",
  "slides": "iampava.com/slides/web-technologies-2021",
  "email": "pava@iampava.com"
}
{ about you }

πŸ‘¨β€πŸŽ“πŸ‘©β€πŸŽ“

πŸ”₯ TW πŸ”₯

Official Lab Page

Official Course Page

βœ” HTML
βœ” CSS
βœ” JavaScript

{

By the end of the course you:

πŸ”₯ will have acquired confidence to start basic Web projects on your own
πŸš€ will have worked on a personal project which showcases your skills 
🎈 will have worked with multiple colleagues and thus grow your team-work skills 
πŸ“ will have learned the fundamentals of the Web

in order to make the most out of this:

πŸ“ you'll have to do a lot of learning outside lab hours
❓ ask questions whenever something is unclear
πŸ‘¨β€πŸ’» you'll have to do a lot of coding -> that's why we have the "homework" exercises

⭐ Projects will be published soon on https://iampava.com/web-technologies ➑ teams of 2 or 3

⭐ If you don't like any of them, feel free to submit one yourselves

⭐ Read more about the projects & evaluation here: https://profs.info.uaic.ro/~busaco/teach/courses/web/

VS Code
Firefox
glitch.com
codepen.io

Tools

πŸ”— devdrive.io

Every week I'll post in-advance exercises for the next lab!

OK, let's do this!

😎 An open platform

πŸ”¨ for building apps, games & awesomeness

πŸ”— Shareable with just a link

The Web

{ DEMO }

⭐ JavaScript

⭐ PhP

⭐ C#

...

usually a browser, but not always!

client ↔ server

built in pretty much any language we can think of

let's inspect the network traffic of a public website

HTML β–Ά

This

is

<img src="...">
<p> Lorem ipsum...</p>
Self-closing
Needs a closing tag!

Elements/tags

<img src="/bob.png">
<p>
  Hi!
  <img src="bob.png">
</p>
Elements can have attributes
Or contain other elements
<button
    data-speed="1" 
    type="button"
>
  1x
</button>

... or custom attributes!

<!DOCTYPE html>
<html>
  <head>
    <!-- ... -->
  </head>

  <body>
    <!--  ...  -->
  </body>
</html>

structure of any html page

HEAD

Elements that describe our website or links to other resources.

<title> FrontEnd.ro </title>
<meta 
  name="description"
  content="ÎnvaΘ›Δƒ FrontEnd" 
/>
<meta property="og:image" content="https://frontend.ro/main-seo-image.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />  
<link rel="stylsheet" href="/style.css" />

and others...

body

Elements that are part of the page and with which the user can interact with. This means most HTML elements

⭐ Containers

header, main, footer, aside, section, div, ul, li

* most used elements

⭐ Text

h1, h2, h3, p, span, strong, pre, code

⭐ Media

img, picture, video, audio

⭐ Forms

form, label, input, select, textarea

⭐ Actions

a, button

Let's code!

html best practices

⭐ Organizing  most web pages

<header>
<main>
<footer>
<aside>

⭐ If there's an <img>, let there be an alt

<img src="/images/avatar.png" 
     alt="Bob's avatar" />

⭐ If it takes you to another page it's an anchor

<a href="/settings"> Settings </a>

⭐ If it does something when clicking it, it's a button

<button type="button">
  Save progress
</button>

⭐ Always put labels on inputs

<label>
  <span> Email or username*</span>
  <input type="text" name="emailOrUsername">
</label>

⭐ If there's an input, there should be a form

⭐ Aaaand, if there's a form ➑ add a submit input/button

<form>
  <label>
    <span> Email or username*</span>
    <input type="text" name="emailOrUsername">
  </label>
  <button type="submit"> Login </button>
</form>

⭐ Keep HTML as minimalist as possible! NO, REALLY!

Any other best practices you'd like to share?

Let's code!

#1

#2

#3

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

πŸ’” Β  css Β  πŸ’–

Week #2

To be honest...

sometimes css is a pain in the a**

but it can also be 😍

First things first!

border: 5px solid black;

background: blue;
value
property

units

⭐ percentage (%)

⭐ vh/vw

⭐ em

⭐ rem

⭐ px

Β 

Β 

...

Try to avoid fixel px dimensions whenever

My favorite ❀

Where do we put it?

#1 inline

<p style="font-weight: bold"> 
    A simple styled paragraph...
</p>

πŸ‘Ž Avoid this at all* times

* most

#2 same file

<html>
 <head>
   <style> 
    h1 {
        text-align: center;
    }
   </style>
 </head>
 <body>
   <h1> Smth </h1>   
 </body>
</html>

πŸ‘Ž Avoid this at all* times

* most

#3 External

<!--  index.html -->
<html>
 <head>
   <link rel="stylesheet" href="./style.css">
 </head>
 <body>
   <h1> Smth </h1>   
 </body>
</html>
/* style.css */
h1 {
  text-align: center;
}

πŸ‘ Do this at all* times

* most
@media screen and (max-width: 500px) {
  nav {
    background: blue; 
    border: 5px solid black;
  }
}

@media screen and (orientation: landscape) {
  nav {
     width: 100%;
  }
}

Based on device

  • @media (prefers-color-scheme: dark) {
      body { background: black; }
    	
      h1, h2, h3 {
    	color: #fff;	  
      }
    }
@media (prefers-color-scheme: dark) {
  header,
  footer, 
  main {
	color: #fff; 
    background: #000;
  }
}

everything is a box (rect)

Elements Tab / DEMO

Display

Determines weather it's block or inline and the inner layout for it's children.

block

inline-block

inline

all the available width. Next element will come below

just the width it needs. Next element comes inline

just like inline-block, only that width/height have no effect

FLEX

the go-to method for semi-complex layouts.

⭐ Make sure you LEARN & USE IT in the project!

Position

Where to "position" an element inside the our Website.

Static

Default position of all elements.

⭐ from Top to Bottom

⭐ from Left to Right

absolute

Position it based on some parent's/ancestor's position

The first one with a position other than static

{
  top: 1em;
  right: 10%;
  bottom: 20px;
  left: 2vh;
}

relative

Position it relative to it's default static position

#1 Slightly adjust it's position by a couple of units

#2 To absolute position children according to itself

Usecases

fixed

Position it based on the viewport or the first ancestor with a transform property.

Scroll to top button on blogs

Fixed side content, ads, etc

Usecases

{
  transform: scale(1.5); 
  /*   transform: rotate(10deg); */
  /*   transform: translateX(5em); */
  /*   ... */
}

Sticky

Default (static) position until the scroll reaches it. Then it sticks!

{ DEMO }

⭐ position

⭐ width

⭐ height

⭐ border

Use only those props:

⭐ top/right/bottom/left

#0

#1

Extra prop: "transform"

#2

Extra prop: "transform"

#3

<p>
 Text
 <span> Help info </span>
</p>

TEXT

Help info

Extra prop: "background"

#4

<main>
 <div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
 </div>
</main>

*Pseudo-selector: nth-child

#5

@media screen and (max-width: 500px) {

}

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

css Β  #2

Week #3

FLEX ❀

flex
items
Flex Container

Β most common props

.gallery {
  display: flex;
  flex-flow: row wrap; 
  /*  row no-wrap; column wrap; ... */
  
  justify-content: space-between;
  /*  space-evenly; center; ...  */
  
  align-items: center;
  /* space-between; space-evenly;... */
}

{ DEMO }

Selectors

Which HTML element/elements we want to style?

by tag

* {
  font-family: sans-serif;
}

h1,
h2,
h3 {
  text-align: center;
}

by class

<button type="button"> Log In </button>
<button type="button"> Register </button>
<button type="button"> Sign Out </button>
<button type="button" class="btn-round"> 
    Log In 
</button>
<button type="button" class="btn-round"> 
    Register 
</button>
<button type="button" class="btn-green"> 
  Sign Out 
</button>
.btn-round {
  border-radius: 50%;
}

.btn-success {
  color: #fff;
  background: green;
}

by id

<p id="hello"> 
    A simple styled paragraph...
</p>

<style>
    #hello {
        font-weight: bold;
    }
</style>

It's all about how specific you are!

<img 
    class="square-image round-image" 
    id="profile" src="user.jpg" 
    alt="user profile"/>

<style>
    img {
        border: 1px solid black;
    }
    
    .round-image {
        border-radius: 50%;
        border: 5px dotted red;
    }

    .square-image {
        border-radius: 0;
        border: 5px dashed green;
    }
    
    #profile {
        border: 2px solid blue;
}
</style>
1)#ID
2).Class
3) TagName
πŸ’₯ !important
  • <style>
    
    .red {
        color: red;
    }
    
    .blue {
        color: blue;
    }
    
    </style>
    
    <p class="red blue"> Bob </p>
    <p class="blue red"> Alice </p>
    
<style>

.red {
    color: red;
}

.blue {
    color: blue;
}

</style>

<p class="red blue"> Bob </p>
<p class="blue red"> Alice </p>

Hmmmmm...?!

some more Selectors

parentΒ  rule

.raining .human {
  /* 
    "human" class elements
    inside "raining"-class  elements
  */
  
  display: hidden; 
  position: under-blanket;/
}

& rule

.valentines.in-love {
  /* 
    both "valentines" & "in-love" 
    classes
  */
  text-decoration: make-up;
}

> selector

main > .card {
  /*  
   * Elements with class 'card' which 
   * are a direct  child of a  
   * 'main' element 
   */
}

BEM: Block element modifier

BEM is naming pattern to keep our CSS clean and our minds sane! πŸ˜…

blocks

Elements that make sense on their own.

eg: image gallery, login form on home page...

<body>
    <div class="gallery">
      
    </div>
</body>

elements

They make sense only as part of a block.

eg: image in an image gallery, form group in a form, etc

<body>
    <div class="gallery">
      <img class="gallery__image" />
    </div>
</body>

modifiers

An element or a block might have a certain state, like success, error, etc

<div class="gallery">
  <img class="gallery__image" />
  <img class="
              gallery__image  
              gallery__image--downloaded
              " />
</div>

πŸ‘‡ Let's finally style it πŸ‘‡

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

html & css recap

Week #4

Let's discuss the projects πŸ‘‡

https://iampava.com/web-technologies

Projects

<Br />

media-queries

.gallery {
  display: flex;
  flex-flow: row wrap;
}

.gallery img {
  width: 30%;
  margin-top: 1em;
  margin-bottom: 1em;
}

@media screen and (min-width: 500px) {
  .gallery img:nth-child(2) {
    margin-left: 5%;
    margin-right: 5%;
  }  
}

@media screen and (max-width: 500px) and (min-width: 350px) {
  .gallery img {
    width: 45%;
  }
  
  .gallery img:nth-child(2n + 1) {
    margin-right: 10%;
  }
}

@media screen and (max-width: 350px) {
  .gallery img {
    width: 100%;
  }
}

Media query example

transforms

#logo {
    tranform: scale(1.1) rotate(35deg);
    transform-origin: center;
}

transitions

πŸ”΄

πŸ”΄

.5 sec
#logo {
  transition: transform .5s ease-in;
}

#logo:hover {
  transform: scale(1.1);
}
property
timing
function
duration

animations

πŸ”΄

πŸ”΄

A
A

πŸ”΄

A

πŸ”΄

A
#logo {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }

  50% {
    transform: rotate(180deg);
  }

  100% {
    transform: rotate(360deg)
  }
}
iteration count

Let's CODE πŸ‘‡

to keep in mind

⭐ Valid HTML

⭐ use flex & variable dimensions when possible

⭐ responsive design

⭐ deploy it on Github pages (bonus)

practical recommendations

✏ sketch the general outline of the website on paper (mobile first)

πŸ“ give each "component" a unique class name so there are no collisions

πŸ‘¨β€πŸ’» start small by implementing the components first

πŸ“¦ notice duplicate code and extract in re-usable classes

πŸ” REPEAT πŸ‘†

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

Week #5

back-end development

Download and install XAMPP if you've chosen PHP!

πŸ”— Download link

php basics

⭐ we can have PHP only files or mix them with HTML for inserting content into the page

<!DOCTYPE html>
<html lang="en">
<head>
    <title>PHP & HTML</title>
</head>
<body>
    <h1> Some header </h1>
    <?php 
        $today = date('d/m/Y');
        echo "<h2> Today is " . $today . "</h2>"; 
    ?>
</body>
</html>
index.php
all variables must start with $

concatenate strings with . operator

⭐ there are no type-declarations needed when we create new variables

<?php 

$name = 'Bob';
$age = 31;
$isMarried = false;

// ...

⭐ Arrays are actually key-value pairs & the keys don't necessarily have to be numbes, as we are used to

<?php 

$phones = ['Bob' => 0740000000];
echo sizeof($phones); // 1

$loteryNumbers = [11, 5, 3];
$loteryNumber['smth'] = 'smth else';

echo  sizeof($loteryNumbers); // 3

foreach($loteryNumbers as $element) {
  echo $element;
}

⭐ PHP has support for OOP style programming via Classes

<?php 

class Human {
	public function __construct($name, $age) {
    	$this -> name = $name;
        $this -> age = $age;
    }
    
    public function greet() {
    	echo 'Hello! I am ' . $this -> name . '. Nice to meet you!';
    }
}

class Programmer extends Human {
	public function __construct($name, $age, $preferedLanguage) {
        parent::__construct($name, $age);
        $this -> preferedLanguage = $preferedLanguage;
    }
    
    public function code() {
    	echo 'Nom nom, I am coding in ' . $this -> preferedLanguage;
    }
}

$fiiDeveloper = new Programmer('Bob', 31, 'PHP');

$fiiDeveloper -> greet();
echo '<br/>';
$fiiDeveloper -> code();
?>

reading data from forms

βœ… Add a action attribute to the form specifying the path the the PHP script handling the submit

βœ… Add a method attribute to the form configuring what HTTP Verb to use (usually GET or POST)

On the client

On the server

βœ… Use the global arrays $_GET or $_POST to read the submitted data

βœ… Add the name attribute to all inputs/textareas/selects so that the server can read their values

LET'S CODE

PHP & JSON

JSON is one of the most popular data formats out there, used frequently on the Web to exchange data from client-server. - Working with JSON

<?php 
    $jsonAsText = file_get_contents("./gallery.json");
    $galleryArr = json_decode($jsonAsText);
    
    foreach($galleryArr as $image) {
    	echo '<div>
        	<img src="'. $image -> src. '">
            <p>'. $image -> description .'</p>
        </div>';
    }
?>
index.php
[{
    "src": "./images/barcelone.png",
    "description": "Sunset in Barcelone",
    "date": "22 June 2019"
}, {
    "src": "./images/madrid.png",
    "description": "Quiet street in Madrid",
    "date": "23 June 2019"
}]

gallery.json

LET'S CODE #1

#2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Calendar.php</title>
    <style>
        body {
            font-family: sans-serif;
        }
        li {
            margin: .5em 0;
        }
    </style>
</head>
<body>
    <?php 
        include_once './calendar.class.php';

        $myCalendar = new Calendar();
        
        // Add next week's schedule
        $myCalendar -> add('04 Apr 2021', '09:00AM', 'Team coffee');
        
        $myCalendar -> add('03 Apr 2021', '2:00PM', 'TW Grupa B3');
        $myCalendar -> add('03 Apr 2021', '12:00PM', 'TW Grupa X');
        $myCalendar -> add('03 Apr 2021', '10:00AM', 'TW Grupa B1');
        
        $myCalendar -> add('02 Apr 2021', '6:00PM', 'Prepare for TW');

        // Get next week's schedule
        $nextWeekSchedule = $myCalendar -> getSchedule('01 Apr 2021', '05 Apr 2021');

        echo '<h1> Next week: </h1> <ul>';
        foreach($nextWeekSchedule as $entry) {
            printEntry($entry);
        };
        echo '</ul>';
        
        // Get the schedule for Apr 3rd
        $apr3 = $myCalendar -> getSchedule('03 Apr 2021');
        echo '<h1> On 3rd Apr: </h1> <ul>';

        foreach($apr3 as $entry) {
            printEntry($entry);
        };

        function printEntry($entry) {
            echo '<li>
                Date: <strong>'. $entry -> date .'</strong> | 
                Time: <strong>'. $entry -> time.'</strong> | 
                Description: <strong>'. $entry -> description .'</strong>
            </li>';
        }
    ?>
</body>
</html>

Implement the Calendar class so that the code above runs flawlessly and outputs

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

MVC pattern

Week #6

MVC is one of the most popular back-end patterns out there, and the one I recommend when building your project. πŸ”₯

Controller(s)

Model(s)

view(s)

πŸ‘¨β€πŸ­

⭐ this is where all the interaction with our database happens (storing & retrieving data)

⭐ consists of Classes/Objects/Functions  depending on your app 

⭐ is passed by the Controller to the View for Rendering

Model

⭐ what the User sees and interacts directly with

⭐ will render part of the model/models

⭐ should only contain very simple logic, like iterating through data and simple if-else

views

⭐ where the logic happens

⭐ it connects the Model with the appropriate View based on the URL

⭐ it also responds to form submit and decides what view to render next

controller

Demo

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

πŸ“… Week 8 deadline: 11 Apr 2021

Sessions & Database

Week #7

πŸͺ cookies

&

πŸ’Ύ Sessions

cookies

Information about a user stored on it's computer (in the browser).

Β 

Primarily used to track us all over the internet... πŸ˜…

<?php
$preferredLang = 'RO';

setcookie("PreferredLanguage", $preferredLang, time() + 3600);
?>
<?php 

if(!isset($_COOKIE['PreferredLanguage'])) {
  echo 'No cookie set';
} else if($_COOKIE['PreferredLanguage'] === 'RO') {
	echo 'Salut';
} else {
	echo 'Hello';
}

Setting up a cookie that expires in 1 hour regarding the language preference

Reading the cookie later in a different page

Sessions

Similar to cookies but they store information about a user on the server.

How do they work? πŸ€”

Sessions

βœ… A cookie having a unique ID - calledΒ  Session ID - is stored on the client (browser)

βœ… On the server there's some data attached to that ID

βœ… When the user goes back to the server, the cookie is read and thus the data attached to that ID is found and can be accessed

<?php    

/** 
    START - Persist session for 2 hours,  
    even after closing the browser.
    
    Needs to be called only once, when starting the server.
*/
 
 $TWO_HOURS = 60 * 60 * 2;
 ini_set('session.cookie_lifetime', $TWO_HOURS);
 ini_set('session.gc_maxlifetime', $TWO_HOURS);
 
 session_start();

 if(isset($_SESSION['count'])) {
   $_SESSION['count'] ++;
 } else {
   $_SESSION['count'] = 1;
 }

 echo $_SESSION['count'];
?>

Continuing from our gallery exercise last week, let's add πŸͺ Cookies to persist the date

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Gallery.php</title>
    <link rel="stylesheet" href="./gallery.css">
</head>
<body>
    <header>
        <h1> Gallery.php </h1>
    </header>
    <main>
        <form action="." method="POST">
            <div>  
                <label for="date">Date </label>
                <input type="date" name="date" id="date" value="<?php 
                    if(isset($_POST['submit'])) {
                        echo $_POST['date'];
                    }
                ?>">
            </div>
            <button type="submit" name="submit">Filter by date </button>
        </form>
        <div class="gallery">
            <?php 
                $filter = NULL;
                if(isset($_POST['submit'])) {
                    $filter = $_POST['date'];
                }

                $images = json_decode(file_get_contents('./gallery.json'));
                foreach($images as $i) {
                    if(!$filter || strtotime($i -> date) === strtotime($_POST['date'])) {
                        echo '
                        <div>
                            <img src="'. $i -> src .'" alt="'. $i -> description.'" >
                            <p>Date: '. $i -> date .' </p>
                        </div>
                    ';
                    }
                }
            ?>

        </div>
    </main>
</body>
</html>
[
  {
    "src": "https://images.unsplash.com/photo-1593642532009-6ba71e22f468?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
    "description": "Laptop",
    "date": "10 Mar 2021"
  },
  {
    "src": "https://images.unsplash.com/photo-1615125468484-088e3dfcabb6?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3fHx8ZW58MHx8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "description": "Car",
    "date": "11 Mar 2021"
  }
]
gallery.json
index.html

Implement a simplistic user login using Sessions

  • read user credentials from a JSON file
  • persist user ID in Session
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User login</title>
</head>
<body>
    <form method="POST" action="">
        <label>
            <span> Username </span>
            <input type="text" name="username" required />
        </label>
        <label>
            <span> Password </span>
            <input type="password" name="password" required />
        </label>
        <button type="submit">Login</button>
    </form>
</body>
</html>
<?php 
  $CONFIG = [
    'servername' => "localhost",
    'username' => "root",
    'password' => '',
    'db' => 'test'
  ];

  $conn = new mysqli($CONFIG["servername"], $CONFIG["username"], $CONFIG["password"], $CONFIG["db"]);

  if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
  } else { 
    echo "Successfully connected to DB";
  }
?>

Sql + xampp = ❀

πŸ‘‡ Connecting to a MySQL database πŸ‘‡

We're using Prepared Statement to prevent this πŸ‘‡

query'ing the db

inserting data

<?php 
 $username = "Bob";
 $pass = "12345";

 $insertStatement = $conn -> prepare("INSERT INTO users VALUES(?, ?)");
 $insertStatement -> bind_param("ss", $username, $pass);

 $insertStatement -> execute();
 $insertStatement -> close();
?>
<?php 
  $getUsersStatement = $conn -> prepare("SELECT * FROM users WHERE username = ?");
  $getUsersStatement -> bind_param("s", $username);
  $getUsersStatement -> execute();

  $users = $getUsersStatement -> get_result();

  foreach($users as $row) {
      echo $row['username'];
      echo ' -- ';
      echo $row['password'];
      echo '<br/>';
  }
?>

retrieving data

<?php 
  $countUsersStatement = $conn -> prepare("SELECT COUNT(username) FROM users");
  $countUsersStatement -> execute();

  $row = $countUsersStatement -> get_result() -> fetch_row();
  echo "We have " . $row[0] . " rows"; 
?>

Let's use the same Gallery exercise as before and instead of a JSON file, let's use an SQL Database

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

User authentication

Week #9

There are multiple methods for Authentication suitable in different scenarios

βœ” APP Authentication

βœ” API Authentication

βœ” "on my behalf" authentication

API Key

Session Cookies

JWT

OAuth

πŸ‘¨β€πŸ’» DIY
Identity Management Solutions (eg: Auth0)

Let's DIY so we get a peak behind the "curtain"

  • Let's use Sessions/Cookies for automatic transfer to the server

Β 

  • After login, let's store in Session the username and hashed password.

Β 

  • When re-visiting the page, read the credentials and if they're a match, "log in" user
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./app.css" />
  <title>Home page</title>
</head>

<body class="home-page">
  <header>
    <h1> Home Page </h1>
  </header>


  <main>
    <form method="" action="">
      <label>
        <span> Username*</span>
        <input required type="text" name="username">
      </label>
      <label>
        <span> Password*</span>
        <input required type="password" name="password">
      </label>
      <button type="submit">
        Sign in
      </button>
    </form>
  </main>
</body>

</html>
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

body * {
  font-family: inherit;
}

h1 {
  font-size: 4em;
}

h2 {
  font-size: 3em;
}

h3 {
  font-size: 2.5em;
}

a {
  font-size: 1.5em;
  text-decoration: none;
  font-family: inherit;
  border-bottom: 2px solid currentColor;
  color: rgb(3, 169, 244);
  font-weight: bold;
}

header {
  position: relative;
  color: #fff;
  text-align: center;
  padding: 0.5em 0;
  background: rgb(3, 169, 244);
}

header h1 {
  margin: 0;
}

header a {
  color: #000;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 2em;
}
.home-page main {
  display: flex;
  margin-top: 10em;
  flex-flow: row wrap;
  justify-content: space-around;
}

.home-page img {
  max-width: 10em;
}

.home-page main a {
  text-align: center;
}

/* Product page */

.product-page main {
  display: flex;
  align-items: center;
  flex-flow: row nowrap;
  justify-content: space-around;
  min-height: calc(100vh - 7em);
}

.product-page img {
  max-width: 50%;
  max-height: 50vh;
}

.not-found-page {
  text-align: center;
  padding: 0 3em;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.not-found-page h1 {
  margin-top: 0;
}

.not-found-page a {
  margin-top: 2em;
}

.not-found-page h3 {
  font-weight: normal;
}

label {
    margin: 2em 0;
    display: block;
}

label > span {
  display: block;
  font-weight: bold;
}

input {
    padding: 0.5em;
    border-radius: 0.5em;
}

Starting code πŸ‘‡

Let's implement the same authentication into an MVC app

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises