FOCUS · build log

The build log · newest first

A month of building a task list
to replace Todoist

Every entry comes from the repo's history: commits, merged pull requests and the decision log, where each choice is written down with what it rules out.

The rules it is built by

00
  • No AI in the appQuick Add, dates and repeats are plain code. The one model in the system lives in a sidecar, runs once per request, and can be removed without changing the app.
  • Every write is recordedAll changes go through one service layer, inside a transaction, with an audit row. Nothing is hard-deleted.
  • Decisions are dataWhere a model decides something, it decides once and returns data a person can read and fix; plain code does every repeat.
  • Secrets stay secretNo password on a command line or in output. Keys live in the system vault or as owner-only files, never in the repo.
  • Proof before trustA backup counts once a restore has been shown to work. A deploy counts once the app answers as the new version.

Entries

10-2026
  1. The focus board, and three milestones

    • Designed the focus board: projects grouped under five headers, progress rings from GitHub milestones, and a "Hand to Claude" button. The look went through several mock-ups, each answering the owner's notes, to "ember ledger".
    • Set up the headers in the live list, so the board has real groups to show.
    • Wrote the worth record and gave the repo three milestones: two weeks of daily use, someone else using it for a week, and later.

    issue #27 · WORTH.md

  2. One home for every project

    • Ran the worth gate for making this app the place every project and idea lives: 2.9, GO, on one condition: prove the backups restore first.
    • Built a restore test that brings the newest nightly dump back in a throwaway copy with no network, and compares counts with the live app, which it only reads. It passed.
    • Gave projects six small facts (state, summary, next, site link, archive reason, public) and a read-only feed that lists only the public ones, field by field, so a new field cannot leak by accident.
    • Loaded every project from the plan and the GitHub catalogue in one run that can be repeated without making duplicates, and added a private search.
    • Ideas reach the website only when tagged public.
    • Made the deploy stop on a failed build, and check that the app answers as the new commit.

    issue #21 · pull requests #22 to #26

  3. "Claude, remind me when..."

    • A task tagged @claude is picked up by a watcher sidecar. Claude runs once and writes a small watch rule into the task; plain code checks it hourly and pushes to the phone when it comes true.
    • Rules only fetch public web pages, refuse redirects, and are readable and editable in the task itself.

    pull request #20

  4. Pairing with a six-digit code

    • A new device types the code from an authenticator app and gets its own key, once. Before this, adding a device meant opening a server port and copying a key by hand.
    • Wrong guesses lock pairing for a few minutes, and each key can be revoked on its own.
    • Wrote the owner and user guide: first-run setup, sign-in, invites and login recovery.
  5. The phone widget

    • A home-screen widget shows today's tasks through one narrow, read-only door, so the phone no longer holds a key that can change everything.
    • On 10-14-2026 done items gained their labels, so the habits widget can tick off what was done today.
    • Three fixes to the deploy script on the way.
  6. Phone app and sharing

    • An installable phone app with a bottom bar, card rows, an Upcoming strip, Browse, Search, Filters, Settings and Notifications.
    • Projects can be shared with another person by invite.
  7. Day one: from contract to running app

    • Wrote the contract every package builds against, then the core (Quick Add, repeats, views), the server with its MCP tools, the web app and the deploy.
    • Imported the old Todoist account, including deadlines and completed history. Output shows counts only, never task titles.
    • Added a large automated test suite and fixed every bug it found at the root, with no test weakened or skipped. One of them: @1pm was being read as a label, so the 1pm reminder never came.