Work / Aakalan / Wiki / Surfaces
expense-receipt
Surfacecanonicalverified 2026-09-23
SURFACE.MOBILE.EXPENSE.RECEIPTSummary
An expense with a bill photographed, including the state where the photo has not uploaded yet.
Raw wireframe
- .context/designs/mobile/expense/receipt.html
Why it is drawn this way
The pending-upload line is the state that makes the offline promise honest.
The expense is already saved and the photo is still on the phone; saying so
beats a spinner, and it beats pretending it is done — which is what writing
receiptPath up front did, showing every other member a path to an image that
was not there. See local-first-ledger.
Tapping opens it full-screen. A bill photographed at a table is unreadable
at thumbnail size, which is the whole reason it was taken. The full-screen
viewer itself is a Modal in the app and is not drawn — recorded in routes.js
under missing.
A wireframe of a receipt is about where the image sits and what it costs,
not what is in it. Hence the .shot stand-in rather than a photograph.
Deleting the expense deletes the image for real — the one thing in this product that is not soft-deleted. Keeping the record does not require keeping a picture, and an image nobody can reach from any screen is a bill somebody forgot they uploaded.
On free with no photo attached, this card is absent entirely. This screen is about an expense that already exists, and an upsell in the middle of it would be an advert rather than an offer; the place somebody is actually deciding is add, which carries the Pro mark there.
Related
Sources
- src/components/expense/receipt-card.tsx
- src/services/receipts.ts
Every project of mine is written down like this.
Read the résumé