Skip to content
Ritesh FirodiyaGet in touch

Work / Aakalan / Wiki / Surfaces

recurring

Surfacecanonicalverified 2026-09-23

SURFACE.MOBILE.RECURRING

Summary

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é