Planet4.Me docs
Open the app

#Tasks

A task is a one-shot commitment; completing it destroys it. A recurring task is the exception, and its rule is fixed rather than learned — rent is due on the 1st whether or not you paid on time last month. nextOccurrenceAt is always derived from the rule and never typed in.

Completing a recurring task re-arms it onto the next slot of its own grid rather than marking it done, so completing late cannot drag the schedule later with it. A pending occurrence whose day has passed stays visible on that day — late exists — but lateness is never MARKED: the row and the calendar state the plain date in the same muted voice as any other, and there is no red, no badge, and no count of things you failed to do.

A detail line's detected facts (the same detectFacts the notes use) render as at most two compact row chips on a second line of the row, a link's chip reading only its host at rest (shortFactLabel) — outside the label button, which owns the tap that edits, and an anchor may not live inside a button anyway. They hide while the detail is being edited. ComingUp and the Regulars note render task text too and deliberately get no detection: those are whole-row controls with no second line to give.

A task lives in a group — the namespace the notes share, wearing the same names on both tabs: the built-ins Personal (stored as 'personal', with the older 'home' folded onto it by canonicalGroupId in the reader; nothing migrates, and every task written before the field existed reads back there) and Work (in a shared household, only while something is filed under it — see Households), plus the household's own. The Tasks tab shows GROUPS ONLY — Personal, Work, then the top-level customs by name, each with its rolled-up count, and nothing else; every to-do lives inside a group. A level's cards sit in ONE container (.group-door): rows inside a single raised surface, hairlines between, one size smaller than a list card — the rows keep their .card classes, which the smoke suite counts. The container wears a title row (.door-head: "Groups", how many, a caret) that folds the rows away and back; the fold is a per-device preference in localStorage (groupDoorFolded:{surface}:{level}), one per door and level, so folding Work's subgroups leaves the root as it was. Above the container sit the level's controls: the level search (see Search, below) and the New group link. Each card opens /tasks/{groupId}, the group's own screen: the level search and its capture at the top, the New group link that files a subgroup here, its subgroup cards (top-level groups only — a subgroup's screen is to-dos alone, by the ceiling), then its to-dos. Adds (typed, captured, or asked for) land on the group that is open. Holding a custom card offers Remove among its other actions, and only when the group is empty through its subtree; the built-ins have no documents, so they carry no hold at all. A group made here exists for the tasks only — the notes door does not show it until something real crosses.

The door also carries a view switch — Groups or All — and All is the one view that crosses shelves: /tasks/all, every open to-do at one level, whatever group it is filed on. Shelves are the default and the reason the app is legible, but they cannot answer "what is there, everywhere?", and no screen could before this one. Its own static route, and the switch is two LINKS rather than a toggle, because a view is a place — linkable, stable across a reload, and where a to-do's tag chip lands, none of which component state could offer; it sits ahead of /tasks/:taskListId in the router, since static outranks dynamic and "all" would otherwise read as a group with that name. The switch (ViewSwitch, one component on all four screens) rides both doors and both flat views, so each says which of the two is on screen and the other is one tap away; it is absent on a door with nothing in it either way, as the row it replaces was. The flat view wears the door's own title — "Tasks", "Notes" — and no Back, because it is a mode of that page rather than a place under it; the switch is the way between the two, and backName names either mode by the door. Three narrowings, all in the query string beside each other and all from the header: ?q= (the search grammar — words, #tags, @people), ?g= (a group from the filter sheet, expanded through groupSubtree), and ?sort= (the sheet's Order). Every row names its own shelf there, which is the one thing it cannot otherwise say. There is no capture box — a to-do typed here would have no group to land on — and no completed toggle: completing is the end of the thing, everywhere.

The Notes door carries the same switch, and All is /notes/all: every active note, whatever group it is filed on, with the same three narrowings in the query string and the same reasoning behind each. It renders ordinary NoteRows — so a row archives, holds to move, and carries its counts exactly as it does on its own shelf — and every one of them wears its group as a chip that goes there. No New button, for the reason there is no capture box on the to-dos'. No archived shelf: that is a recovery surface and it belongs beside the notes it recovers. No questions shelf either, since those are keyed to a group and /questions already crosses them. selectNotes takes the same only set selectTasks does, so a folder means a folder and everything in it on both.