The Learning Path Challenge 🛤

This is a work-in-progress guide. Its aim is to help you learn all the skill necessary for working with Sealcode’s software stack, by giving you small challenges.

The challenges are designed to not hand-hold you too much and encourage looking up certain things online yourself, as this is possibly the most important task in web development :wink: Remember that even senior developers have to search online for answers related to coding on a daily basis.

You can skip any step if you find that you already feel confident in the topics it covers, or if it’s marked as optional.

1. Freecodecamp JS Course


What does it teach

Basics of programming algorithms and JS syntax.

How do I know if I did it right

It’s an interactive course that will tell you once you’ve 100%-ed it

2. A small project with colors


Create a small JS application using node.js. Use npm to install the chalk library and use it to make the output of your node.js program colorful.

The application should work in a terminal (cli) and should display numbers from 1 to 100. Numbers divisible by 3 should be red, numbers divisible by 5 should be blue, and numbers divisible by both 3 and 5 should be purple. All other numbers should be white.

Make it so you can run the application using the npm start command by making changes to the package.json file.

How do I know if I did it right

There should be a package.json file in the root of your project directory. It should have been automatically created by npm. You should know what each part of the package.json file does.

There should be a node_modules directory also created by npm.

1 Like

3. HTML Basics


Finish the “Learn HTML by building a Cat Photo App” part of this freecodecamp course:

Then, create an HTML file from scratch. Make it a small html document about one of your hobbies, or maybe a list of your favourite memes. Make sure to include some images and that those images have properly set alt attribute.

How do I know if I did this right?

You should have some intuition on how to write HTML documents. The HTML document should properly display in the browser if you double-click it. It should be valid HTML syntax - you can test that with this tool:

1 Like

4. A small web application with koa


Create a small web application that serves two pages: and One should say “Hello, world”, and the other should say “Goodbye, world”.

This tutorial will be helpful:

How to know if I did this right

Running npm start should start the app. Then the user should be able to visit and in the browser and see the proper text.

What the app sends to the browser should be proper HTML.

1 Like

5. Prettier auto-formatter

Prettier is a popular code for automatically formatting many file formats, including JavaScript files. It becomes sort of a de-facto standard and helps keep formatting and whitespace consistent across all project files. It’s designed in a way that helps diffs being readable during code review.

What to do

Set up Prettier in the code editor of your choice – see the “Editor Support” section at Configure it so files are automatically configured with prettier.

Make sure you have auto-formatting enabled:

How do I know if I did this right

Download (1.5 KB) and open it in your code editor. Add two newlines at the end of file and save the changes. Prettier should kick in and make this file much easier to read.

6. HTML Forms

HTML forms are the most traditional way of creating user interactions. Mastering them is a crucial skill when developing fast and lightweight web apps.

What to do

Using this guide as support, create a form.html file somewhere on your hard disk. That form should be a valid HTML file and contain one form. The form should have three fields:

  • name: the name of the pet – a text input
  • type: the type of the pet – a dropdown (<select>) with at least three animal spiecies to choose from. It should not have a default value - it should be empty by default.
  • birthday: the date of birth of the pet – a date input.

There should also be a “submit” button. The “name” and “type” fields should be required - that is, if the user tries to submit the form and those fields are not filled in, the form submission will be prevented and the user notified of the missing values in fields.

Each form input should have a label. Clicking the label should focus the input corresponding to that label (see <label>: The Label element - HTML: HyperText Markup Language | MDN)

Do not use JavaScript - all of the above can be achieved with pure HTML.

How do I know if I did this right?

Opening the file in the browser should show the form and the three fields. The submit button should be visible. Trying to submit an empty form should cause an error message to be displayed. The HTML file should be validated with The W3C Markup Validation Service. Submitting the form successfully should change the address displayed in the browser from something like file:///home/user/sealcode/form.html to file:///home/user/sealcode/form.html?name=Tussi&birthday=2023-11-13&type=dog

7. HTML Forms - security pt. 1

When handling sensitive data in a form, you may want to used a masked input when asking for user’s password, for example, in order to prevent someone looking over the user’s shoulder from learning their credentials. This has a native solution in HTML.

What to do

Create a login.html file that contains a login form. It contains two fields - username and password. Each field should have a clickable label just as in the previous HTML challenge. The form should have a submit button, with a changed text - it should say “Log in” instead of “Submit”, but behave the same as a regular submit button.

Username and password should both be required. The password should be at least 8 characters long - if the user tries to submit a shorter password, the submission should be prevented and appropriate error message should be displayed.

Do not use any JavaScript within that HTML file. All the functionality described above can be achieved with just pure HTML.

Open the form in the browser, and enter a username and password and submit the form. Observe your password being revealed in the URL. We’re gonna fix that in future exercises.

Now fill in username and passwords fields again in that form. Open the Developer Tools (Firefox DevTools User Docs — Firefox Source Docs documentation) and pick the “Inspector” tab. Find the password input, double-click on the “type” attribute and change it to text. Observe the password being revealed in plain text within the password input.

8. HTML Forms - security pt. 2

In this challenge we’re going to prepare an HTML form more suited to transmitting sensitive information.

What to do

Create a small koa application (or develop one created in one of the previous exercises). Add two endpoints: GET /login and POST /login.

GET /login should just reply with an HTML of a form like we did in the previous exercise.

POST /login should reply with HTML containing a “logged in!” message if the user is logged in, “Wrong username or password” otherwise. The only working credentials should be login: admin and password: adminadmin.

In the form, make sure the action attribute of the <form> element points to /login, and method is POST.

Use GitHub - koajs/koa-body: koa body parser middleware to handle the input sent as a part of a POST request.

Explain in what way this approach is better than the one described in the previous exercise

9. HTML Forms - security pt. 3

What to do

Open the form created in the previous exercise in a browser. Open the developer tools and remove the minlength attribute from the password input element. Observe that now the browser allows the user to submit a password that is shorter than 8 characters.

Create a signup form that does not has this vulnerability. Validation should be done both on front-end and back-end side.

  • If the user tries to submit a password that is too short, the browser should display an error without submitting the form, just as it was the case in previous exercise, using the minlength attribute

  • If the user circumvents this protection and submits the form, the server should reply with “this password is too short”


10. Advanced HTML Forms with server-side rendering - pt. 1

What to do

Create a new endpoint in your koa router. Make it respond with HTML. The HTML should display a number. At first the number is 0. There are two buttons: +5 and x5. Pressing +5 should increase the number by 5 and display it. Pressing x5 should multiply the number by 5 and display it. It should be possible for two or more users to display that form and use it without one user’s actions influencing the state of the other user’s form.

Don’t use JS on the front-end.

Use the following hints if you need help:

Hint 1

You can use multiple submit inputs within one form. Here you could use two – one for each of the possible actions

Hint 2

Each of the submit inputs can have a name and value attribute. They can have different values. The value of the button that has been clicked will be appended to the body of the POST request.

Hint 3

Give one of the inputs name="action" and value="+5", and the other name="action", value="x5". Use if/else to perform the proper action on the server-side.

Hint 4

You can use <input type="hidden"> within the form to make the browser send the current number to the server with each form submission. This way you will know what new number to show.

1 Like

11. Advanced HTML Forms with SSR - pt2. What the hex?

This challenge is about re-creating the What the Hex? online game. It’s a game that helps you to learn how to “see” the colors encoded as Hex.

Check this to learn what we mean by “hex” or “color hex” in webdev context.

What to do

Create a new endpoint - /start-game/. It should show the user three buttons - “5”, “10”, and “15”. When a user presses any of those buttons, the game is started with the specified (5/10/15) numbers of colors to choose from. We’re going to call the number n from now on.

When the game begins, the user is shown a hex code of a color and n squares, each of a different color. One of those squares is of the exact color represented by that hex code, the others are randomly chosen. Under each square, there’s a button that says “My choice”. If the user presses the button under the correct square, a “Congratulations” text shows up. Otherwise, a “Game over” screen shows up.


Generating random colors

This stackoverflow answer got you covered: javascript - Random color generator - Stack Overflow

Making colorful squares

You can generate a square with a specified background color using such a snippet of html:

<div style="height: 100px; width: 100px; background-color: #ffcc22"></div>
1 Like

12. Advanced HTML Forms with SSR - pt3. What the hex? Let me retry!

This challenge is about expanding the game you wrote in the previous exercise to bring its functionality closer to the original game. One thing missing in what was described in the challenge above is the ability to retry - it’s frustrating if the user immediately loses if they provide the wrong answer! Make it so if they pick a wrong color, that color is greyed out, but but all other color boxes remain visible, all until there’s only one box left.

1 Like

13. HTTP Query Params - some quality of life improvements to the game

What you’ll learn

  • HTTP Query Params in Koa

What to do

Assume you’re an advanced player of What The Hex and you’d like to have more random colors on screen to really test your skills.

One way to achieve that would be to add more buttons with numbers on them to the first screen. But let’s find another way – one that will let the user choose any number of colors they like.

We can use query params - the part of the URL that sits after the ?. Make it so if someone goes to /start?difficulty=<n> (where <n> is a number someone picked, like /start?difficulty=48), they start a new game with the specified amount of squares

This article might be helpful with reading the query parameters in koa:

13. Session management - a multiplayer game what the hex, pt 1

We’re going to step-by-step turn this into a multiplayer game. We’re going to add a way for the game to remember people’s usernames. We need a way to distinguish users from one another. This is what Cookies are for! You can learn more about them here:

What you’ll learn

  • session management with HTTP Cookies
  • file-based data persistence

What to do

Create a /set-name endpoint. It should display a form that asks the user for their chosen username (at least 5 characters). Once the user submits the form, and their username is unique (noone else has chosen the same username), we create a new session and set a proper cookie (see below). If the username is taken, we display an adequate message and let the user try again.

How to handle login

For now, we’re not doing any password or account management. So a user is considered “logged in” once they find a unique username for themselves, but there won’t be a possibility for them to log in using a different browser. It’s just a minimal version of a login service that will help us learn how Cookies work and give us something to build upon in the future.

When “logging in” a user we need to create a unique ID for them (you can generate one with crypto.randomUUID() - Crypto | Node.js v21.5.0 Documentation. And send it to the end-user using Cookies (name the cookie session-id). We need to store the UUID server side and have an object that maps those UUIDs into usernames.

Keep the session data as a JSON file - see File system | Node.js v21.5.0 Documentation

After login

Once the user is logged in, the UI should display a piece of text that says ”You are logged in as [username]”. If the user opens the app in another browser, they should not be logged in in that other browser. Add this information to the UI of all game-related endpoints in the project.

1 Like

14. Session management - a multiplayer game what the hex, pt 2.

We’ll now create a more robust login, where one user can have multiple sessions and can log in using a pre-set password.

What you’ll learn

  • More fundamentals of authentication in web
  • HTTP status codes


What to do

Disable the /set-name endpoint for now (you can comment it out). Create a /register endpoint that returns an HTML form. The user have to pick a username and a password. The password must be at least 8 characters long. This condition should be checked both front-end side and back-end side. After submitting the form:

  • if the user chose a username that’s already taken or a password that’s too short, an appropriate error message should be displayed and an HTTP status code 422 should be returned (422 Unprocessable Content - HTTP | MDN)
  • if everything is OK, a confirmation should be displayed and a 200 HTTP status code should be returned.

Create a /login endpoint that behaves in a similar fashion (try re-using some of the code with the /register endpoint!). Submitting this form successfully should return status code 200 and set the appropriate cookie.

Create a /logout session that destroys the session. You don’t have to delete the cookie from the client - just remove the session information from the persistent storage file.

One user should be able to have multiple active sessions.

Update the code to only use only asynchronous, promise-based file access methods (File system | Node.js v21.5.0 Documentation)

15. Session management. What if the database leaks? • A multiplayer game what the hex, pt 3.

Databases sometimes leak. If we store the passwords in the database, then once they leak, anyone who has access to that leak can log in as that particular user.

In order to prevent that type of attack (or at least make it much, much harder to perform), passwords should not be stored in the database. But then, how do we know if the user entered the correct password? The answer is: hashing functions.

Read more here:

For a more in-depth guide on hashing passwords, see:

What you’ll learn

  • basics of authentication where credentials are stored as hashes

What to do

Update your code to work as previously, but store the user passwords as a PBKDF2 hash (see Crypto | Node.js v21.5.0 Documentation).

16. Database • A multiplayer game what the hex, pt 3.

What we have so far is now more secure, but given the asynchronous read/write access to the file that’s necessary to have reasonable performance, we have a different type of vulnerability - possibility of data loss due to a Race condition - Wikipedia. If two users make two requests in very short amount of time, the write operation of one can override the changes made to the file by the other user. Ask your mentor if you’d like to see a demonstration of this phenomenon occurrence on your own code.

What you’ll learn

  • How to install and run a MongoDB database using Docker;
  • How to connect to the database from within your application;
  • How to share one connection to the database across multiple requests.

What to do

  1. Install the docker engine - Install Docker Engine | Docker Docs

  2. Use docker run --name mongo --network host mongo to start a mongo server on one of your terminals. (If you’re curious, read more about mongo in docker here: Docker & MongoDB | Containers & Compatibility | MongoDB). If it displays a lot of messy data, it means it’s probably working! You can kill it with ctrl+c, just like any other app in the terminal.

  3. Use the official mongodb library from npm to connect to your database: mongodb - npm

  4. Use insert and find instead of the write/read file functions in order to store user info and session info. Use separate collections for sessions and users.

  5. Make sure to run client.connect() function only once per application runtime, to make each request faster. You can use the following snippet for inspiration:

let db_connection;

function get_db_connection(){
     db_connection = client.connect
   return db_connection

17. Taking turns. • A multiplayer game of What the Hex, pt 4.

Now is the time to implement the core of the multiplayer game!

The game is going to be played between two logged in users.

What you’ll learn

  • advanced state management

What to do

Create a /start-multiplayer endpoint. Visiting it should only work for a logged-in user. If the user is not logged in, they should be redirected with a 302 redirect to the login page. If the user is logged in, a new game is created. A game is stored in a collection somewhere in the mongo database. The game is identified by a random UUID string (Crypto | Node.js v21.5.0 Documentation). The player that’s creating the game is the presented with a link (/join-multiplayer-game?game_id=12312312312312321) they can copy and send it to another logged in user via any means. Both the players have to visit that link. When a player visits that link, they are presented with a “join this game” button. Once two players join that game, the game is started. Players take turns. One of the players is chosen at random when the game is starting. Each user can see the other user’s choices, and cannot click a color they or the other player have already clicked. The first user to pick the right color - wins!

In this version, we’re not doing automatic refreshing of the game state. Users will have to refresh the page repeatedly when they’re waiting for the other user’s action. We’re gonna change that in the future, don’t worry :slight_smile:

1 Like