Tangy is building your next step
Shaping the lesson around what you want to make.
Tangy is building your next step
Shaping the lesson around what you want to make.
Computer Science
Build a small, working to-do web app from real project files. You will use your existing HTML and CSS foundation, add a focused Express server, connect a tiny browser interface with vanilla JavaScript, and finish with a simple app you can run and demonstrate.
Shape the Standalone To-Do Page
2 lessonsStart with the learner's established HTML and CSS skills to create the complete static interface before introducing the server or browser networking.
Add the Express Foundation
3 lessonsIntroduce the runtime and server in small steps: first run a server, then serve the finished static page through it.
Connect the Browser to Tasks
3 lessonsUse vanilla JavaScript and the Fetch API to replace the static empty state with live task data from the Express server.
Finish and Prove the Small App
3 lessonsComplete the two task actions, make the behavior understandable, and verify the finished project as a runnable piece of work.
Public lesson
Your HTML structure skills are already strong, so this is a short bridge into the full-stack app: you’ll create the page that future JavaScript and server code can rely on.
The page will expose this contract:
| Part | Purpose | Stable hook |
|---|---|---|
| Page heading | Names the app | h1 |
| Task form | Receives a new task | #task-form |
| Task input | Holds the typed task | #task-input |
| Task list | Holds rendered tasks later | #task-list |
| Empty state | Explains what an empty list means | #empty-state |
Tasks
Open your react-fullstack-app project and find the file that currently renders its main page.
index.html.src.Work in that existing page or component. Don’t create a disconnected practice file—the later JavaScript and server work need to find this interface.
Tasks
Look at the current page and decide where these pieces belong:
The list should start empty. JavaScript will add task items later.
Tasks
Adapt the scaffold below to your project’s existing file and styling conventions. Replace each bracketed value with wording that fits your app. Keep the IDs stable because later code will use them.
<main>
<h1>[your app name]</h1>
<form id="task-form">
<label for="task-input">[label for the task]</label>
<input
id="task-input"
name="task"
type="text"
placeholder="[short instruction]"
required
/>
<button type="submit">[button text]</button>
</form>
<section aria-labelledby="task-list-heading">
<h2 id="task-list-heading">[heading for the task list]</h2>
<ul id="task-list">
<!-- Future task items will be inserted here. -->
</ul>
<p id="empty-state">[message shown when there are no tasks]</p>
</section>
</main>
<main>
<h1>[your app name]</h1>
<form id="task-form">
<label for="task-input">[label for the task]</label>
<input
id="task-input"
name="task"
type="text"
placeholder="[short instruction]"
required
/>
<button type="submit">[button text]</button>
</form>
<section aria-labelledby="task-list-heading">
<h2 id="task-list-heading">[heading for the task list]</h2>
<ul id="task-list">
<!-- Future task items will be inserted here. -->
</ul>
<p id="empty-state">[message shown when there are no tasks]</p>
</section>
</main>
The label and for/id pair makes the input understandable to screen readers and clickable by name. The ul gives future tasks the correct list structure, even though it is empty for now.
If your project uses JSX rather than an HTML file, translate the attributes into JSX syntax where needed, such as className instead of class. Keep the same element roles and IDs.
Tasks
Start the project and open the page. Confirm that you can see:
Tasks
Then click the label. The text cursor should move into the input. Try submitting the empty form; the browser should prevent submission because the input is required.
Tasks
Open the browser console and run these checks one at a time:
document.querySelector("h1")
document.querySelector("#task-form")
document.querySelector("#task-input")
document.querySelector("#task-list")
document.querySelector("#empty-state")
document.querySelector("h1")
document.querySelector("#task-form")
document.querySelector("#task-input")
document.querySelector("#task-list")
document.querySelector("#empty-state")
Each line should return an element, not null.
Tasks
Finally, inspect the page with keyboard navigation. Starting outside the form, press Tab and confirm that you can reach the input and submit button in a sensible order. The page is ready for the next lesson when the structure is visible, the empty list has no task items, and all five selectors find the intended elements.
4 modules · 11 lessons
Shape the Standalone To-Do Page
Add the Express Foundation
Connect the Browser to Tasks
Finish and Prove the Small App
Learn by building your own version.
Remix this public project to open the workspace, follow the guided build, and let the AI mentor teach you through the work instead of doing it for you.