March 1, 2020

How to build a web app in 15 minutes

In this tutorial I'll show you how to build a web app with user login and data storage in just 15 minutes. We'll create small web app for managing personal notes with a frontend written in HTML & JavaScript and a backend managed by Stackprint. For user management and authentication we'll be using Auth0.

1. Configure Auth0

In the first step we're going to set up user management and authentication with Auth0.

Create Auth0 Account

To get started, you'll have to create an Auth0 account and configure some things so we can use it for in our web app:

  • Navigate to https://auth0.com/ and click Sign Up
  • Choose an email address, password and again click Sign Up
  • In the next step, choose a tenant domain and select your preferred region.

Configure Application

The next step is to create an Application in Auth0 and configure it so we can access it from the frontend:

  • Under Getting Started select Create Application
  • In the next step, enter the name of your application and select Single Page Web Applications
  • Navigate to Settings and set the following properties:
  • Allowed Callback URLs: http://localhost:3000
  • Allowed Web Origins: http://localhost:3000
  • Allowed Logout URLs: http://localhost:3000

Configure API

In addition to the Application, we'll have to create an API in Auth0. The API configuration ensures that Auth0 generates the right kind of access tokens for us later on:

  • Navigate to APIs and click Create API
  • As Name enter the URL that will be the base URL of your Stackprint project, e.g. https://p.stackprint.io/stackprint-notes
  • Ensure the Signing Algorithm is set to RS256

2. Configure Stackprint

The next step is to create a REST API to store personal notes with Stackprint. To protect the API, every request needs to contain a valid access token created by Auth0 based on the previous configuration:

  • On your Stackprint Dashboard, click New project
  • In the next step, enter a project name and path
  • Toggle Allow JWT Authentication and enter the JWKS URL for your Auth0 account, e.g. https://stackprint-notes.eu.auth0.com/.well-known/jwks.json
  • Click Submit
  • In the next step you don't have to change the default backend configuration, it already defines a REST API where users can access their personal notes. Just click Deploy.

2. Build frontend

The frontend is going to be a single page written in HTML and plain Javascript for simplicity. We'll provide basic functionality to login, logout as well as creating and listing personal notes.

Define structure and initialize Auth0

{% c-block language="html" %}
<!DOCTYPE html>
<html>
 <head>
   <title>Stackprint Example</title>
   <script src="https://cdn.auth0.com/js/auth0-spa-js/1.2/auth0-spa-js.production.js"></script>
 </head>
 <body>
   <button id="login">Login</button>
   <button id="logout">Logout</button>
   <div id="notes" style="visibility: hidden;">
     <div id="note-list"></div>
     <div id="create-note">
       <input id="note" /><button id="submit-note">Submit</button>
     </div>
   </div>
   <script>
     (async () => {
       const projectBaseUrl =
         "<stackprint project base url, e.g. https://p.stackprint.io/stackprint-notes>";
       const auth0 = await createAuth0Client({
         domain: "<auth0 account url, e.g. stackprint-examples.eu.auth0.com>",
         client_id: "<auth0 application client id>",
         redirect_uri: "http://localhost:3000",
         audience: projectBaseUrl
       });
       /* following code goes here */
     })();
   </script>
 </body>
</html>
{% c-block-end %}

Create a single file index.html and paste the content from the snippet. Here we're setting up a basic HTML document defining the structure of our frontend. We create two buttons, one to login and one to logout. An additional block wraps the list of existing notes as well as an input field and button to create a new note.

In the JavaScript section we're initializing an Auth0 client from the auth0-spa-js library that we're going to be using for user authentication in the next step. Make sure to fill in your Stackprint project base URL, your Auth0 account URL and the client id of your Auth0 Application.

Login & logout

{% c-block language="js" %}
/* handle click on login */
document.getElementById("login").addEventListener("click", async () => {
  await auth0.loginWithRedirect();
});

/* handle click on logout */
document.getElementById("logout").addEventListener("click", () => {
  auth0.logout();
});

/* handle login callback  */
try {
  await auth0.handleRedirectCallback();
} catch (err) {
  /* not coming from redirect */
}
{% c-block-end %}

Next, we're adding click listeners for the login & logout buttons. Clicking the login button will forward the user to a login page hosted by Auth0. Once the user has successfully signed up or logged in on that page, it redirects back to our frontend. We're handling that redirect from the Auth0 login page in the last block.

Load personal notes

{% c-block language="javascript" %}
/* get user access token, load notes on success  */
const accessToken = await auth0.getTokenSilently();
document.getElementById("notes").style.visibility = "visible";
const loadNotes = async () => {
  document.getElementById("note-list").innerHTML = "";
  const result = await fetch(`${projectBaseUrl}/notes`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  });

  const notes = await result.json();
  notes.forEach(note => {
    const noteElem = document.createElement("p");
    noteElem.innerHTML = note.text;
    document.getElementById("note-list").appendChild(noteElem);
  });
};

await loadNotes();
{% c-block-end %}

Once the user has successfully logged in, we can request an access token from Auth0. That token has the JWT format and holds signed user information that Stackprint uses to determine the identity of the user to load personal notes for.

We're requesting the user's notes from the Stackprint backend and append them to the HTML document.

Create personal notes

At this point the note list will always be empty since there's no way to create notes yet. Let's fix that!

{% c-block language="javascript" %}
/* create note  */
document
  .getElementById("submit-note")
  .addEventListener("click", async () => {
    await fetch(`${projectBaseUrl}/notes`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`
      },
      body: JSON.stringify({
        text: document.getElementById("note").value
      })
    });
    loadNotes();
  });

{% c-block-end %}

We're adding a handler for the button to create a note that sends the content from the input field to the Stackprint backend. Upon success, the list of notes will be refreshed to include the newly created note.

Test the app

You can run a local HTTP server on port 3000 to test the web application you have just created. A simple way to do so using Python is running:

{% c-block language="bash" %}
py -m http.server 3000
{% c-block-end %}

in the directory you've created you index.html in.

How to build a web app result

That's it, you've successfully built a web app with Auth0 & Stackprint, feel free to play around and add some notes!🎉

The full frontend code can be found here: https://github.com/stackprint/example-notes-javascript.

Latest Posts