Build a Minimal To-Do App with Express and Vanilla JavaScript
Computer Science
Build a Minimal To-Do App with Express and Vanilla JavaScript
Build a Minimal To-Do App with Express and Vanilla JavaScript
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.
What you learn by building this
- Create and run a minimal Express server from project files
- Serve a semantic to-do page and static assets from Express
- Use vanilla JavaScript to read form input and update the page without a framework
- Call server endpoints with fetch and render returned task data
- Implement minimal in-memory task creation, completion, and deletion
- Keep the project scope intentionally small and verify its visible behavior
Learning Journey
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
Define the task interface
Lesson 3.1 — Build the task interface
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
1. Find the real page
Open your react-fullstack-app project and find the file that currently renders its main page.
- In a plain HTML setup, this may be
index.html. - In the React app, it may be the main page or component inside
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
2. Sketch the structure before writing it
Look at the current page and decide where these pieces belong:
- One main page heading
- A form for adding a task
- A labeled text input and submit button
- A section containing the future task list
- A message shown while there are no tasks
The list should start empty. JavaScript will add task items later.
Tasks
3. Add the interface
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
4. Check the page in the browser
Start the project and open the page. Confirm that you can see:
- one clear main heading
- a task input with a visible label
- a submit button
- a task-list heading
- the empty-state message
- no task items yet
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
5. Check the interface contract
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.
Course Outline
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.