Tasks with priorities, due dates and tags, kept in this browser, with a full store, a second tab and a document written by an older version all handled instead of losing the list.
Initializing in your browser…
Write SEO, Open Graph and X card tags with every value escaped for an attribute, checked against the protocol, and the cut shown per platform.
Work and break cycles on a monotonic clock, so a session is not ended by the system clock changing, with the running session and today figures kept if you reload.
Build a favicon from text, an emoji or an image and get a real favicon.ico holding 16, 32 and 48 pixel images, seven PNGs, a web app manifest and the head tags, in one archive, with the ICO parsed back from its own bytes before it is offered
You want a quick task list for today that survives a page refresh but never touches an account or a server.
Entered tasks
Ship hotfix · Review PR #214 · Reply to Dana · Book standup room
Current board
✔ Ship hotfix ✔ Review PR #214 ☐ Reply to Dana ☐ Book standup room 2 of 4 done, open items kept after reload
Tasks persist in your browser's localStorage, so closing the tab and reopening it keeps the list intact, while nothing is ever uploaded. It is deliberately minimal, add, check off, reorder, clear, for the cases where opening a full project tracker is overkill.
Tasks with priorities, due dates and tags, kept in this browser. The saving is the part that was rebuilt: a full store, a second tab and a document written by an older version are all handled and said out loud instead of losing your list.
The three tools on this site that keep a document in your browser (this one, the checklist creator and the Zettelkasten notes) all carried the same four faults before September 2026, and each was measured rather than reasoned about.
**A full store took the tool off the page.** `localStorage.setItem` throws `QuotaExceededError`, and an exception out of a React effect body reaches the nearest error boundary. Driven with the setter made to throw, all three tools vanished from the page and none of them said anything: the write was lost and the work on screen went with it. Now a failed write leaves the change on screen and puts the reason where the person who made it can see it, including how much room is left.
**Every page load wrote an empty document first.** The save effect ran on mount with the state still empty, before the load effect update had rendered. Measured in a production build, the writes on load were `[]` and then the real document, in that order, so there was a window on every single load in which your whole document was an empty array in storage. (In development it was worse than a window: React strict mode double-invokes effects, the empty save landed between the two runs of the load effect, and a seeded item was simply gone after one reload.) The document is now read in the state initialiser, so nothing is ever written before it has been read.
**A second tab silently destroyed the first tab work.** Each write replaces the whole document from the writing tab own state, and nothing listened for the `storage` event. Measured: tab one wrote two items, tab two, opened when there was one, wrote its own, and storage was left holding one. Now each tab is told when another one changes the document and is offered the choice, rather than one of them losing quietly.
**`JSON.parse` succeeding is not validation.** A document written by an older version parses perfectly and then throws on the first field that is read. Every record is now checked field by field: what can be repaired is repaired and the page says what it did, what cannot be read is left alone rather than overwritten, and an imported file goes through exactly the same check as the stored one.
One more, particular to this tool: **two of its five statistics tiles never appeared at any screen width.** They were written `hidden xs:block` inside a `grid-cols-3 xs:grid-cols-5` grid, and `xs:` is not a breakpoint in this project, so both were simply hidden and the grid was always three columns. High Priority and Due Today are both visible now.
A stored list carrying one good task and one record with no text at all loads the good one, drops the other, and says so: "The saved data was written by a different version: 1 could not be read at all and was left out."
The saving was the weak part, and it is the part that was rebuilt.
Both tabs are told when the other changes the list, rather than one of them quietly winning.
Export to JSON and import it on the other one; the import is checked the same way the stored document is.
In this browser, under this site, in localStorage. They are not sent anywhere, which also means they are not backed up and are not on your other devices. Export the JSON if the list matters.
The save is refused by the browser. The page tells you, keeps the change on screen so you can copy it, and shows how much room the list is using out of the roughly 5 MB a browser gives one site.
That was the old behaviour: both tabs wrote the whole list and the last one won. Now each tab is told when the other changes it and you choose which version to keep.
Yes. So will a private window, and so will some settings that block site data. Export the JSON.
This runs as client-side JavaScript. Keys, tokens, payloads, and other inputs never leave your device.