LifeOS
← projects
shippedOct 2026 · 5 min read · 1 diagram

Payback

Stack JavaScript · Supabase · Vercel · Gemini

The itch

Splitting a trip's costs between friends needs everyone on board, and getting a group to sign up for an app before dinner is where most splitters fail. Then someone pays a restaurant bill with five dishes and three taxes, and the group has to work out who had what. Payback cuts both problems down. There are no accounts. Whoever has the trip's link can see it and add to it. Bills can be scanned instead of typed.

What it does

You create a trip with a name, a currency and a list of people, then share the link. Each expense records who paid and how it splits: equally, by amount or by shares. "By amount" starts as an equal split. Amounts you type stay fixed, and the people you haven't touched share the rest, even when the total changes. A settle-up view suggests the fewest payments that clear every balance, and "Mark paid" records a full or partial payment. Changes sync live to everyone with the trip open.

The bill scanner does the most work. Photograph a receipt and it comes back as a "who had what" list. Every item starts as shared by everyone, so you untick the people who didn't have it. Tax, service and tip spread in proportion to what each person ordered.

Everyone on a trip appears as a tilted white sticker with their name underneath. Each trip picks one set of robots, 3D emoji, shapes or cats, and anyone can swap in their own photo.

How it works

It's deliberately small. The page is a single static HTML file with plain JavaScript, with no framework, no build step and no package.json. The browser talks to Supabase directly for data and live updates. The only server code is one Vercel function, with no dependencies, that handles bill scanning.

Scanning a bill

The scanner runs on Gemini's free tier, which meant building fallback by hand: a per-minute rate limit gets one quick retry, a daily limit moves on to a second model with its own quota, and typing an expense manually always works. The Vercel AI Gateway was considered and passed over as more than two models need.

Money is integer cents throughout. When a split leaves a remainder, the leftover cents go to the first people in the list so the parts always add up to the total. Settle-up matches the largest debtor with the largest creditor until everyone is square.

What got hard along the way

The printed total on a bill is the truth, and getting a model's reading to agree with it took three passes. Indian restaurant bills often print GST and then CGST and SGST beneath it, so a naive sum counts the tax twice. The reconciler drops a charge that equals the sum of two or more charges of the same kind, but only when exactly one such choice makes the bill add up. Then a real café bill came back one paisa over. Each tax line on the bill had been rounded separately, 60.3625 printed as 60.37 twice. Gaps under one rupee are now treated as rounding and folded into a round-off line. If the lines still don't match, the model is asked to re-check once, with the numbers quoted back to it, and the closer answer wins. Save stays blocked until the lines add up exactly.

Other bugs came from where the app actually gets opened. Links get shared on WhatsApp, and in-app browsers like WhatsApp's and Instagram's silently block prompt() and confirm(), so every dialog became an in-page one and deleting means tapping twice. iPhone photos copied to a laptop arrive as HEIC, which Chrome and Firefox can't decode. The page tries the browser first and only lazy-loads a 3 MB HEIC decoder when it has to.

The avatars went through several rounds. Generated faces came first and were dropped because people wanted them to look like themselves. Random cat photos from an API had inconsistent quality and unclear licences, and cutting cats out of photos failed on about half of them. What stayed is 40 hand-picked public-domain cats, Microsoft's Fluent 3D emoji, and robots and shapes drawn on the phone by DiceBear, so names never leave the page.

Where it stands

Payback is live and in use, with a real trip on it. Trips, the three split types, editing, the bill scanner, settle-up with partial payments and the sticker avatars are all shipped, and a design review's eleven points were closed on 2026-10-11. Voice logging is being built on a separate branch. Logins are parked until there's a reason for them.