TutorialsPreview
Build a Todo App

Build a Todo AppLesson 2

LearnReferencebeginner12 minBuild a Todo App

Structure & style the app

Lesson 1 of 4 — the markup and CSS the rest of the course brings to life.

You will learn

Semantic structure for a small app and how a stylesheet turns bare markup into something you would actually use.

Prerequisites

None. If you can open a file, you can do this lesson.

01

Step 112 min

Lay down the markup and the look

GoalA static todo layout exists and looks finished — before a line of behaviour.

Good apps are built shape-first. We write the index.html structure (a form, a <ul>, a footer with filter buttons) and a styles.css that makes it calm and dark. Two rows are hard-coded so you can see the design; lesson 2 replaces them with real, JavaScript-driven items.

project · todo-app · Structure & style Open in Code
index.htmlHTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Todo</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main class="app">
<h1>Today</h1>
<form id="new-todo">
<input id="title" name="title" placeholder="What needs doing?" autocomplete="off" />
<button type="submit">Add</button>
</form>
<ul id="list" class="list">
<li><span class="check"></span><span class="title">Read the brief</span><button class="remove" aria-label="Delete">×</button></li>
<li class="done"><span class="check"></span><span class="title">Open the editor</span><button class="remove" aria-label="Delete">×</button></li>
</ul>
<footer class="bar">
<span id="count">1 left</span>
<span class="filters">
<button data-filter="all" class="active">All</button>
<button data-filter="active">Active</button>
<button data-filter="done">Done</button>
</span>
</footer>
</main>
<script src="app.js"></script>
</body>
</html>
styles.cssCSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: start center;
padding: 6vh 16px;
font-family: system-ui, -apple-system, sans-serif;
background: #0b0e14;
color: #e7ecf3;
}
.app { width: 100%; max-width: 460px; }
h1 { font-size: 22px; letter-spacing: -0.01em; margin: 0 0 16px; }
#new-todo { display: flex; gap: 8px; margin-bottom: 18px; }
#title {
flex: 1;
padding: 11px 14px;
border-radius: 10px;
border: 1px solid #232a36;
background: #11151c;
color: inherit;
font-size: 15px;
}
#title:focus { outline: none; border-color: #6ea8fe; }
#new-todo button {
padding: 0 18px;
border-radius: 10px;
border: 1px solid #2b3340;
background: #6ea8fe;
color: #0b0e14;
font-weight: 600;
cursor: pointer;
}
.list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.list li {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 14px;
border-radius: 10px;
background: #11151c;
border: 1px solid #1c2330;
}
.check {
width: 18px;
height: 18px;
flex: none;
border-radius: 999px;
border: 1.5px solid #3a4456;
cursor: pointer;
}
.list li.done .check { background: #4ade80; border-color: #4ade80; }
.list li.done .title { color: #5b6675; text-decoration: line-through; }
.title { flex: 1; }
.remove {
border: none;
background: none;
color: #5b6675;
font-size: 20px;
line-height: 1;
cursor: pointer;
}
.remove:hover { color: #f87171; }
.bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16px;
font-size: 13px;
color: #8b93a3;
}
.filters { display: flex; gap: 4px; }
.filters button {
border: 1px solid transparent;
background: none;
color: inherit;
padding: 4px 10px;
border-radius: 8px;
cursor: pointer;
}
.filters button.active { border-color: #2b3340; color: #e7ecf3; }
app.jsJAVASCRIPT
// Step 2 brings this page to life.
// For now the rows in index.html are hard-coded so you can see the design.
preview
The static app at step 1 — press Open in Code to edit it whole.

Before lesson 2

Try it

In Code, change the <h1> from "Today" to your own list name and re-run the preview.

Concepts covered · 1

More like this

R
Reference·intermediate·17 min

Review what comes back like a senior

Models produce confident, plausible, well-formatted code — which is exactly what makes their mistakes dangerous. This lesson is the review rubric: the specific failure classes to hunt for, because "it looks right" is not review.

O
Reference·advanced·18 min

Orchestrate agents without the codebase rotting

Putting it together: context, guardrails, and a verification loop that lets you run coding agents across a real codebase without it drifting into an incoherent pile. This is the senior loop at full speed.

W
Reference·intermediate·16 min

Write the spec the model can hit

A prompt is a specification. The difference between a junior and a senior prompt is the constraints a senior names that a junior leaves to chance. This lesson turns your architecture sketch into a prompt that produces reviewable code.

Liked this one?

Pass it on

Discussion

Be the first to ask

Your questions stay private with the team. We can pin answers to share with everyone.

Sign in to ask a question privately on this tutorial.

Sign in

No pinned answers yet for this tutorial.