Skip to content
Ritesh FirodiyaGet in touch

Work / Aakalan / Wiki / Surfaces

person

Surfacecanonicalverified 2026-09-23

SURFACE.MOBILE.PERSON

Summary

One person's running ledger, totalled across every group.

Raw wireframe

  • .context/designs/mobile/person/person.html

Why it is drawn this way

Totalled across groups, because a settlement conversation is person-to-person. Groups are an accounting convenience; nobody says "I owe you ₹400 from Goa and ₹200 from the flat".

Name and avatar are in the HEADER row. The screen used to spend its first 140px on a second, larger copy of the same avatar over the same name, above a balance card you had to scroll to.

The actions live INSIDE the balance card, and there are never more than two in a row. They used to be four equal-width buttons on one line — Add expense, Remind, Settle up, Invite — each with an icon and a label, on a 390px screen.

Add expense is its own full-width row because it is the reason this screen is open as often as the balance is.

THE LEDGER is oldest first, with the balance after every line. It replaced two sections that between them could not answer the question the screen exists for: "Where this comes from" was a per-group total, and "Shared expenses" was the same expenses newest-first with no settlements in it at all — so the one line that explains why the number dropped was missing, and the reader had to add the rest up themselves.

The running column is only allowed to exist because it is derived. person-ledger.ts asks computeBalances for every delta, so its last row IS the figure in the card above by construction rather than by coincidence.

Per currency, never netted. Somebody you share two groups with can owe you in one and be owed in another, and those do not net into a single figure. See money-in-minor-units.

There is deliberately no fallback to "the first person". An earlier version silently rendered a DIFFERENT person's ledger under the requested route, which is the worst possible failure on a screen about who owes whom; a missing person renders not-found instead.

Related

Sources

  • src/app/person/[id].tsx
  • src/lib/person-ledger.ts

Every project of mine is written down like this.

Read the résumé