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 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
Description
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
Description
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
Description
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
Description
Create a small web application that serves two pages: 127.0.0.1:8080/hello
and 127.0.0.1:8080/goodbye
. 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 http://127.0.0.1:8080/hello
and http://127.0.0.1:8080/goodbye
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 prettier.io. 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 make-me-pretty.zip (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â
2 Likes
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.
Hints
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
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:
https://scribe.rip/getting-request-data-with-koa-6edcd65f8471#c9ae
13. Session management - a multiplayer game of 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 v22.9.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 v22.9.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.
Create a /whoami
endpoint that shows the user their username if they are logged in
1 Like
14. Session management - a multiplayer game of 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
Resources
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 v22.9.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
-
Install the docker engine - Install Docker Engine | Docker Docs
-
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.
-
Use the official mongodb library from npm
to connect to your database: mongodb - npm
-
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.
-
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(){
if(!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
1 Like