Project: A To-Do App
Time to put it all together. In this final lesson you'll build a complete to-do app: adding, completing, editing and deleting tasks, filtering them, and saving everything so it survives a reload. It uses variables, functions, arrays, objects, DOM manipulation, events, delegation and storage — most of this course in about 80 lines.
The finished app
Try it first: add a few tasks, tick some off, double-click a task to edit it, switch filters, then press Reset on the editor — your tasks are still there.
How it's structured
The app follows a pattern used by almost every front-end framework:
- State — a single array,
todos, plus the currentfilter. This is the source of truth. - Render — one function rebuilds the list from the state. It never reads data back out of the page.
- Actions — event handlers change the state, then call
render().
Because the page is always drawn from the state, it can't drift out of sync. React, Vue and Svelte automate exactly this loop — understanding it here makes those frameworks much easier to learn.
Key techniques used
| Technique | Where | Lesson |
|---|---|---|
| Objects in an array as state | todos | 29, 36 |
map, filter, find | Rendering and updates | 31 |
| Spread to update immutably | { ...t, done: !t.done } | 33 |
Creating elements, replaceChildren | render() | 43 |
textContent for user text (XSS-safe) | Task text | 43 |
Form submit + preventDefault | Adding tasks | 44, 46 |
Event delegation with closest and data-* | List and filter clicks | 45 |
localStorage + JSON with try/catch | load(), save() | 41, 48, 54 |
crypto.randomUUID() for IDs | New tasks | 50 |
Challenges
Extend the app in the editor above. Each challenge practises a different part of the course:
- Due dates — add a date input to the form, store
dueon each task, and show overdue tasks in red (lesson 20). - Sort — add a button that sorts tasks alphabetically with
localeCompare(lesson 32). - Inline editing — replace the
promptwith an input that appears in place of the text, saving on Enter and cancelling on Escape (lesson 44). - Keyboard shortcut — focus the new-task field when the user presses / (lesson 44).
- Modules — move the app into your own project, split into
storage.js,render.jsandmain.js(lesson 55). - Sync — load initial tasks from
https://jsonplaceholder.typicode.com/todos?_limit=5withfetchwhen storage is empty (lesson 49).