How to Create a Login Form with Postgres and Javascript - Part 1: Build the Interface with HTML and CSS


In this five-part tutorial, we will create a sign-in system that allows users of your Postgres- and Python-based web application to enter their email and password, check their entry against the email and hashed password we have in the database, and even offer a “I forgot my password” feature that involves sending a link to the uesr via email and showing them a different form that allows them to change their password. This article is part one of that five-part series. In this series, we will address the following: – Part 1: Build the login form using HTML, CSS, and Javascript. Interaction with the database will be absent from this part 1. – Part 2: Validate user input of email and password, create a hash of the user’s password, and compare it to the hash we have in our PostgreSQL database. We’ll use Python for this part of the tutorial. If they verify, we send them on to the rest of your application. – Part 3: Email the user a link if they clicked “I forgot my password.” – Part 4: Serve the user a modified form for creating a new password. – Part 5: Validate, put hash of their new password into the database, and send user to a page with a message.

Overview of this article

In this part 1 of our series, we build a standard login screen and input form using HTML, CSS, and Javascript. We will share all the code you need for this part in one heavily-commented chunk below.

Assumptions and prerequisites

We’ll assume: – You have a users table in your database. If not, please follow the instructions for our “Create Registration System” tutorial here. – You have a web server and site set up, whether local or remote, where you can test your work. – If the server and site are remote, you have set up FTP for uploading the scripts you will be writing. If you are looking for a free and capable FTP client, try FileZilla – You have a basic knowledge of HTML, CSS, and Javascript. A high level understanding should be all you need, as we will be providing all the code you need here, heavily commented. – Later in this five part article you will need basic knowledge of PostgreSQL and Python.

The code

Study the code below, paste it into your favorite code editor, save the file as “sign-in.html“, upload to your server into a folder called “/templates”, and try it out! NOTE: It is very important that you put this file in a folder in the root folder (probably called “httpdocs”) called “/templates”.

        <link rel="shortcut icon" href="favicon.ico">
        <meta name="description" content="Sign in here to play the greatest game ever seen!">
        <!-- In the interest of modularity, once you get this working, -->
        <!-- we recommend you create a stylesheet file and refer to it -->
        <!-- from here using the line below -->
        <!--link href="/css/non-existent-file.css" rel="stylesheet" type="text/css"-->
        <!--  -->
        <script language="JavaScript" type="text/javascript">
       /* checkform() is the overall function called from */
       /* our HTML when the user submits the form */
       function checkform (form)
           /* isEmpty() returns true and alerts the user if they left a field empty */
           function isEmpty (fixwhat, s_called)
               if (fixwhat=="")
               alert("Please enter " + s_called);
               return true;
               } else {
               return false;

           /* charCheck() returns false and alerts the user if they used any non-alphanumeric characters */
           function charCheck(fixwhat)
               var validchars = '@-_.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                   return true;
               } else {
                   alert("Please use only letters or numbers in this field");
                   return false;

           /* isValid is used by the charCheck() function to look through each 'validchars' one at a time */
           function isValid(string,validchars)
               for (var i=0; i< string.length; i++)
               if (validchars.indexOf(string.charAt(i)) === -1) {return false;}
               return true;

           // Check for empty fields
           if (is_empty (form.t_email.value,"your email address")) { form.t_email.focus();  return false;}
           // We only need password if they are signing in, NOT if they want a password reset email
           // later we'll add an extra "if" right here to make sure which form they are submitting
           if (is_empty (form.t_password.value,"your password")) { form.t_password.focus();  return false;}

           //check for weird chars
           if (charCheck(form.t_email.value)===false) {form.t_email.focus(); return false;}
           // later we'll add an extra "if" right here to make sure which form they are submitting
           if (charCheck(form.t_password.value)===false) {form.t_password.focus(); return false;}

           return true ;

        <!-- Some basic styles to set element colors, size, and align our form fields -->
        <!-- As mentioned above, we recommend you place the following CSS into a file -->
        <!-- So that every page of your site can refer to that one CSS file, which -->
        <!-- increases ease of modification in the future. -->
        <style type="text/css">
            html, body {
                padding: 1;
                margin: 1;

            input {
                font-size: 16px;
                font-family: Helvetica, sans-serif;

            body {
                background-color: #66AACC;
                font-family: sans-serif, arial, helvetica;
                padding-bottom: 50px;

            .container {
                background-color: #FFFFFF;
                max-width: 600px;
                margin: 20px auto 0 auto;
                padding: 15px 20px 1px 20px;

            .form-row {
                padding: 10px 0;
                display: flex;

            .form-row label {
                padding-right: 10px;

            .form-row input {
                padding-right: 10px;
                flex: 1;
<!-- Note: later you may wish to add an include pointer (include) to a common header file here -->
<!-- or above this mark, depending on other factors. -->
<!-- Why a common header file? This is so that all pages share the same footer. -->
<!-- Changing the one header file will change the header of every page on your site. -->
<!-- For example, you may wish to put your logo and navigation links in this file -->
<!-- or even have a separate file for header and separate file for navigation. -->

<!-- The message you see below is why we call this a template -->
<!-- message is filled in by the Python file as it calls up this HTML -->
<!-- Later you may wish to separate page title from message -->

<!-- Note: this 'container' class refers to the '.container' we see in the CSS we wrote above -->
<div class='container'>

    <!-- Set up form type and the file to process user input -->
    <!-- Notice how the onsubmit parameter calls our checkform javascript function -->
    <!-- This checks to make sure the user: -->
    <!-- (a) didn't leave any field empty; and -->
    <!-- (b) used only valid alphanumeric characters -->
    <form id='frmSignIn' name='frmSignIn' action='/sign_in?stage=login' method='post' onsubmit='return checkform(this);'>

    <!-- text box for user to enter their Email address -->
    <!-- Notice our input has an id of 't_email'. -->
    <!-- This is used by our checkform javascript function. -->
    <div class="form-row">
      <label for="Email">Email address:</label>
      <input type="text" id="t_email" name="t_email">

    <!-- text box for user to create a Password -->
    <!-- Notice our input has an id of 't_password'. -->
    <!-- This is used by our checkform javascript function. -->
    <div class="form-row">
      <label for="Email">Password:</label>
      <input type="text" id="t_password" name="t_password">

    <!-- button for user to submit the form -->
    <div class="form-row">
      <input type="submit" id="btn_submit_sign_in" value='Sign In'>

    <!-- Close our form -->
    <!-- -------------------------------------- -->
    <!-- Password reset form will go below here -->
    <!-- -------------------------------------- -->

    <!-- -------------------------------------- -->
    <!-- Password reset form will go above here -->
    <!-- -------------------------------------- -->

<!-- Close our container div -->

<!-- Note: later you may wish to add an include pointer (include) to a footer file here. -->
<!-- This is so that all pages share the same footer. Changing the one footer file will change -->
<!-- the footer of every page on your site. -->

<!-- Close the body of our HTML document -->



You’ve now finished part 1 of 5 of creating a login feature for a web application. We have also given you some ideas above for how to make this page and the entire application more modular in the future. Look for part 2 where we’ll use Python to handle the user’s input and route them accordingly.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.