JavaScript in the browser
Build a small interactive page
Combine DOM selection, events, arrays, local storage, fetch, and error handling in one small browser project.
Build a page that lets a visitor save a short reading list.
Keep one state array as the source of truth. Every add, remove, and load updates that array, writes it to storage, then re-renders from it. If you patch the DOM separately, you will eventually show stale data.
Use this item shape:
{
id: crypto.randomUUID(),
title: 'JavaScript modules',
url: 'https://example.com/modules'
}
On startup, read local storage inside try/catch. JSON might be missing, malformed, or from an older version. Validate that the parsed value is an array before you trust it.
Handle the form submit event. Trim the title, parse the URL with new URL(), reject unsupported protocols, and show errors beside the relevant field. Build nodes with textContent and attributes instead of stuffing untrusted strings into innerHTML.
Render each item with a real link and a remove button. Remove by stable id, even when two titles match. Keep keyboard focus somewhere sensible after add or remove.
Add a button that loads one suggested item with fetch(). Show a clear message when the request fails.
Model request state explicitly: idle, loading, success, empty, and error. Disable only the control that would duplicate an in-flight request. Remember that fetch() can resolve with response.ok === false.
Before you call the project done, test keyboard-only add and remove, empty inputs, duplicate titles with different URLs, malformed saved JSON, failed and slow network paths, and a reload after each kind of change.
The goal is one reliable data path through events, arrays, validation, storage, network I/O, rendering, and recovery, not visual polish.
Start with static HTML and no framework so you can see each layer clearly before you hide it behind a library.
Lesson completed