Template
1
Fork 0
todo-list/README.md
Leonardo Devai 259fde814c Review and modernize all 42 projects to the updated standard
Pinned 2026 toolchains (Go 1.26, Rust 1.98/edition 2024, Python 3.14 + uv, Node 24,
Zig 0.16, NixOS 26.05), postgres 18 / mongo 8, lockfiles built from, non-root
runtimes, .dockerignore, per-project LICENSE, READMEs with the git.devai.io clone
line, checkout@v7 CI. Security fixes in the legacy Rust APIs (any-password login,
self-assigned admin, hard-coded JWT secret), JWT alg/exp/sub enforcement across the
blog series, safe markdown links in the frontends, and many smaller bugs — every
project was built, run and exercised end to end.

Adds scripts/publish.sh + a CI publish job that splits every folder into its own
repo at git.devai.io/templates/<folder>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G
2026-09-27 21:10:38 +02:00

1.9 KiB

todo-list

A real to-do app that remembers your tasks after a refresh — built from one array, one render() function and localStorage. It teaches the idea every framework is built on: the data is the truth, and the screen is redrawn from it.

Run

Get it: git clone https://git.devai.io/templates/todo-list.git

Double-click index.html — it opens in your browser and works. Nothing to install, no build step.

Or serve it like production:

docker compose up --build

Then open http://localhost:8080.

How it works

All the tasks live in one array, tasks, of { text, done } objects. Every action — add, tick, delete — follows the same three steps:

  1. change the array (push, flip done, or filter a task out),
  2. save() it to localStorage (as JSON, because it only stores text),
  3. render() — clear the list and rebuild every <li> from the array.

Because the screen is always rebuilt from the data, the two can never drift apart. On load, the array is read back with JSON.parse, so your list is still there after a refresh.

Try it: add a "Clear completed" button (tasks.filter((t) => !t.done)), put new tasks on top with unshift instead of push, or stamp each task with new Date().toLocaleDateString().

Layout

index.html   the form, an empty <ul>, and the "left" counter
app.js       the tasks array, save() and render()
styles.css   the look; follows your system's light or dark mode

Deploy

Push to your own GitHub repo and the shipped workflow (.github/workflows/ci.yml) tests the compose stack, publishes the image to GHCR, and — once you set the DEPLOY_HOST / DEPLOY_USER variables and DEPLOY_KEY secret — deploys it to your server over ssh.


Part of devai.io — the Web Basics track: HTML, CSS & JavaScript, one concept at a time. Next up: countdown-timer.