Recibos
The small ledger that keeps my family's spending fair: two currencies, receipt photos, and math nobody has to argue with.
My mom and I share expenses across one household and two currencies. Groceries in colones, subscriptions in dollars, gas one week, dinner the next. We never fought about money, but we did something almost as corrosive: we kept the accounts in our heads. Whoever paid last felt like they’d paid most, and the end of every month arrived with a small cloud of “wait, didn’t I get the last one?”
The fix wasn’t an app store budgeting suite. Those want categories we don’t use, bank logins we won’t give, and a subscription for the privilege. What we needed was a ledger, in the old sense: a place where every receipt lands, where the math is done one way, in the open, and where “who owes whom” is a number instead of a feeling.
So I built Recibos. That’s the name on our domain, Spanish for receipts, because that’s the whole ceremony: keep the receipt, honor the receipt.
The dashboard, redrawn in this site’s stone. The real one lives behind a passcode, because a family ledger is family business.
Two currencies, zero conversions
The first design decision is the one most tools get wrong: colones and dollars are never converted. There is no exchange rate in the codebase, on purpose. Converting would mean arguing with a moving number every month, and the moving number always feels unfair to somebody. Instead the ledger runs two parallel accounts. Colones settle in colones, dollars settle in dollars, and each month ends with at most two small transfers.
Settling itself is a toggle, not a transaction. When my mom pays me back for June’s colones, she taps settle, and the app records who owed, how much, and when. The history stays intact. Nothing is deleted to make the balance zero, which is exactly what makes the balance trustworthy.
The receipt does the typing
Nobody keeps a ledger that’s annoying to feed. So the entry path had to be shorter than the argument it replaces: photograph the receipt, and the app reads it.
A receipt’s journey. The gold box is the only one that matters: the ledger is the source of truth, everything else serves it.
A Lambda passes the photo to a vision model that pulls out the merchant, date, amount, and currency, then drops the human into a form with everything already filled in. You glance, correct if needed, save. The photo itself is archived to S3, keyed by date, and every entry links back to its receipt. That’s the “clear proof” part: any number on the dashboard can be traced to a photograph of the paper that produced it.
Built like the big ones, sized like a family
Under the hood it’s the same architecture I build professionally, scaled down until it costs almost nothing. A single DynamoDB table holds everything, partitioned by month, expenses and settlements side by side. Two Lambdas behind an HTTP API do the reading, writing, and OCR. The dashboard is a static page of vanilla JavaScript modules, no framework, no build step, served through CloudFront with a passcode gate at the edge. The infrastructure is a Go CDK stack, the domain math is pure Python with a pytest suite, and the dashboard logic has its own tests runnable with nothing but Node.
The whole thing serves two users and costs pocket change a month. But the point was never scale.
Fairness in a family isn’t a transfer of money. It’s a shared set of facts.
Recibos keeps the facts. We just live on top of them.