Typing Practice Website

TL;DR

  • Using cloud resources from AWS to deploy an application offers scalability out of the box at the cost of some vendor lock-in.

  • NextJS can be a go-to choice for static pages.

Most traditional typing practice websites or softwares do not show you a whole lot of information on your progress and on areas where you have room to improve. Therefore, I decided to write my own.

The design

I started with a design in Figma. My design was based on the inspiration I got by searching for other web apps on dribbble.com.

The initial page shows a list of exercises, both public and user created and the history for each of those exercises. Based on feedback I got, I should have also included another landing page that shows how to exactly use the software. But thats for another day.

Concept of the main page of the typing practice site

Concept of the main page of the typing practice site

The statistics section, which is the reason why I started the project in the first place, should show the performance for each individual key as well as statistics for each exercise and how well my performance was across time. I used a linear regression on my own data that could quite accurately predict how well my performance would be on my next exercise. This can give me or other users information on when performance declines and its time to take a break.

The statistics page of the app

The statistics page of the app

Not only should the keyboard show the overall performance, it should also give more feedback when each of the keys is hovered.

On hover, the key information should be shown

On hover, the key information should be shown

The implementation

My deployment considerations

Initially, I implemented the App using "Create React App" but at that time NextJS was also emerging and I switched to that after a couple months. I also started off using JWTs and a DigitalOcean Droplet, which are private virtual machines in the cloud. However, this had the drawback that I was constantly paying for it and I could not scale it to the millions of users I was expecting some day, which is why I switched to AWS. What's especially nice about AWS is that it offers a great tool called CDK, which lets you define your cloud infrastructure as code, more specifically, Typescript. And this is great, because not only can you predictably generate the whole infrastructure with a simple CLI command (with the exception of linking a domain to the API), you also get code completion while writing that code and you are able to create composable structures.

The code below shows how to create a custom class which extends the default LayerVersion from the AWS CDK. This is a very basic example on how to provide default parameters to custom class, but it could also be used in more complex scenarios.

import { Code, LayerVersion, LayerVersionProps, Runtime } from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";

export class LambdaLayerConstruct extends LayerVersion {
  constructor(scope: Construct, id: string, props?: LayerVersionProps) {
    super(scope, id, {
      compatibleRuntimes: [Runtime.NODEJS_14_X],
      code: Code.fromAsset("src/layers/util"),
      description: "Provides Database Handlers",
      ...props,
    });
  }
}

You could then use this new lambda layer like so:

const layer = new LambdaLayerConstruct(this, "TypiLambdaLayer");

The AWS CDK also allows you to distinguish between different environments. On prod you might want to structure your configuration differently from how you would structure it on dev.

Another nice feature about AWS is that it can automatically handle user authentication and authorization for you using Amazon Cognito. Of course, this comes also with its own set of drawbacks. Most notably vendor lock-in. It will not be easy for you to switch from Cognito to another provider.

The final implementation

My final version was almost an exact replica of the initial design with some minor adjustments for easier maintenance and fewer lines of code.

A screenshot of the main interface of the website

A screenshot of the main interface of the website

When a user wants to start an exercise, he has to click on the start button. A window opens and the user can start to type.

The user has to type the correct characters in order to finish the exercise

The user has to type the correct characters in order to finish the exercise

Once the user has finished the exercise, either because the time ran out or the user typed the predefined number of characters, an overview of the exercise will be shown.

The Overview of the Exercise. It includes the characters that were pressed and some other metrics

The Overview of the Exercise. It includes the characters that were pressed and some other metrics

The statistics page lacks a couple of features, such as showing the tiles for the regression results, but it offers a functional dashboard for viewing past results and a filter function.

A Screenshot of the Statistics Page

A Screenshot of the Statistics Page

Future improvements

If I will ever publish this on its own domain and actually open it to the public, I will also have to add further improvements to the UI. Also, as of now, not all critical parts of the applications are tested and users currently cannot register on the site. Thats due to the legal notice requirement (german: Impressumspflicht) in some European countries such as Germany or Austria for pages with economic interests, which requires you to include a "serviceable address" (german: ladungsfähige Adresse). Thus, to publish this site, I will have to rent a mailbox.