Work / Aakalan / Wiki / Surfaces
recurring
Surfacecanonicalverified 2026-09-23
SURFACE.MOBILE.RECURRINGSummary
The recurring rules — active, paused, and stopped.
Raw wireframe
- .context/designs/mobile/recurring/rules.html
Why it is drawn this way
Nothing on this screen is an expense. A rule produces a real expense on its due date and nothing at all before then, which is why there are no greyed-out "upcoming" rows: an expense that has not happened must not move a balance, and one that looks like it might is how people stop trusting a shared ledger.
A rule whose group changed underneath it is STOPPED and says so. It never
guesses a new split — re-dividing a bill among whoever is in the group now would
move real money that nobody discussed. isRuleStranded derives that from the
group on every read rather than storing it, so a member who leaves and comes
back fixes the rule by itself.
Pro lapsing pauses the rules rather than silently not running them. Rent quietly going unlogged is a worse outcome than a paywall, and the banner says that adding the same expense by hand stays free. See pro-never-gates-the-core-loop.
A rule may be DELETED outright, unlike an expense. It is a setting, not a record of something that happened — a-record-is-never-erased governs the expenses it made, not the rule itself.
The catch-up is one expense per occurrence, each dated to its own due date. Two months away means two expenses, never one merged bill: that would be a number nobody agreed and would land in the wrong month's insights. It is capped, so an old device cannot materialise years of rent on a single launch.
Rules live under the user, not the group, even when the expense they make belongs to one: a rule is a private arrangement with yourself about a bill you happen to split.
Related
Sources
- src/app/recurring/index.tsx
- src/components/recurring-runner.tsx
- src/lib/recurrence.ts
Every project of mine is written down like this.
Read the résumé