You built the house in HTML. You decorated it in CSS. Today, you wire up the electricity.
Before the project, one more look back.
At the start of this track, JavaScript was the language that did "behavior," and your first line was console.log('Hello from JavaScript!'). Remember seeing that message appear, and then watching a heading change its own text?
Look at what you know now. You can store and shape data with variables, arrays, and objects, and pack it into JSON. You can make decisions, repeat work, and package steps into functions that remember things through closures. You can find any element on the page, change it, build new ones from data, and remove them. You can listen for clicks, keys, and form submissions, and replace the browser's generic error messages with friendly, accessible ones. You understand why setTimeout(..., 0) runs late, what a promise is, and how await waits without freezing the page. You can load data from a server, handle the times it fails, and remember a visitor's choices between visits.
And you know the why: why === beats ==, why textContent beats innerHTML, why a real <button> beats a clickable <div>, and why the server is always the security guard.
There were surely moments where it didn't work. A null where an element should have been. A Promise {...} where data should have been. A this that went missing. You read the clue, found the cause, and fixed it. That's the actual skill.
I'm genuinely proud of you. Let's finish the house.
In Final Project: Your Profile Page, you built a personal profile page, and in Final Project: Style Your Profile Page, you styled it. Now you'll make it interactive.
This workspace starts with a finished version of that page. The HTML and CSS are done, so you can focus entirely on JavaScript. The script.js tab contains a few preview-only helpers (explained in its comments) and a labeled spot for each requirement. You're welcome to adjust the HTML and CSS too, but keep the ids the requirements mention, because the checker uses them.
Each requirement says what to build, why it matters, and which lesson to review.
Make the #theme-toggle button switch the page between light and dark:
data-theme on the <html> element to the saved choice, or, for a first-time visitor, to 'dark' or 'light' based on prefers-color-scheme.data-theme between 'light' and 'dark', and save the new choice with saveSetting.aria-pressed in sync: 'true' when dark mode is on.Why: A preference that resets on every visit isn't much of a preference. The CSS already has a dark theme waiting for data-theme="dark", so JavaScript only decides when. Review: Saving Data with localStorage and Where CSS Meets JavaScript.
Create an array of at least three interests, and build an <li> for each one inside #interests-list, using createElement and textContent.
Why: Content that lives in data can be sorted, filtered, or loaded from a server later without touching the HTML. Review: Creating and Removing Elements and Arrays.
Write an async function that loads your projects from PROJECTS_URL and shows each one as an <article> (with an <h3> title and a <p> description) inside #project-list.
#projects-status while it works.response.ok, and throw an error if it's false.#projects-status instead.Why: This is the pattern behind almost every dynamic page on the web: ask, wait, check, show, and plan for failure. Review: Loading Data with fetch and Promises and async/await.
As someone types in #contact-message, update #message-count to say how many characters are left (the textarea's maxLength is 200).
Why: Helpful feedback while typing, not after, is the difference between a form that guides people and one that scolds them. Review: Forms and Custom Validation.
Listen for the form's submit event and prevent the default. Then check the name and email fields yourself:
#name-error, #email-error), and set aria-invalid="true" on the field.aria-invalid for fields that are fine.#form-status and reset the form.Why: Specific, visible, accessible messages help everyone finish the form, including people using screen readers and keyboards. Review: Forms and Custom Validation.
const and let only, never var.=== and !== only, never == or !=.textContent, never innerHTML.script.js. The checker reads that file, so code in a <script> added to index.html won't count.Why: These are the habits that keep code readable, safe from XSS, and free of the quiet type-juggling bugs. Review: Best Practices and Common Mistakes.
#projects-status once they load ("3 projects").scroll listener and the hidden property.filter and includes.The tabs on the left switch between these instructions, index.html, style.css, and script.js. The page runs a moment after you stop typing (or when you press Run). About a second after it loads, a small checker at the bottom of index.html tests each requirement and prints a final-project: line in the Console tab for every one that passes, and the Checks tab turns green as they do. Leave the checker at the bottom of index.html where it is. Drag the line between the two sides to give either one more room; on a phone, the Code and Result buttons in the toolbar switch between them. Reset puts the starter code back; press it twice, so a stray click can't wipe your work.
The checker can only see whether each piece works. It can't tell whether your error messages are kind, whether your names are clear, or whether your functions are small. That judgment is yours, which is what the self-check is for.
This is a building project, not a test, so there's no score. Answer each question honestly, yes or no, about your own code. Every "no" is just a pointer to your next improvement.
textContent, including text that came from data?const everywhere a value never changes, and let only where it does?catch blocks, or errors I'm quietly ignoring?If you answered yes to all nine, you've built something you can proudly show a future employer, a client, or your family. If a few came back "no," that's completely normal. Go back and improve them. The second pass is where good developers become great ones.
Your page is structured, styled, and now alive. It remembers people, loads fresh content, and guides visitors through a conversation. That's the complete foundation of front-end web development: HTML, CSS, and JavaScript, working together, each doing its own job.
From here, the book branches out. TypeScript adds types that catch mistakes before your code even runs. Frameworks like React and Vue help you build much bigger interfaces without drowning in querySelector calls. And Node.js takes the JavaScript you already know to the server, where you'll finally build the security guard. Whichever way you go, you're going with a solid foundation. Well done.