DEV Community

Hugo Montenegro
Hugo Montenegro

Posted on

We built a Splitwise alternative where the link is the account. Here is what that forced us to design

Draft skeleton. Rewrite in your own voice before publishing.

The constraint

If your friends have to make an account, they won't. So the room URL had to be the whole product: the invite, the login and the data key in one string.

What that forced

  1. The link is a bearer credential. 16 random bytes, base64url, appended to a readable stem. No recovery, no owner override. Treat it like a key.
  2. Money as strings + BigInt. A Number never touches an amount except for display. Equal splits hand out remainders deterministically. A property test runs 300 random rooms through the client derivation and the server fold and expects equality.
  3. FX locked at entry. Editing an expense never re-prices history. Rates are fetched through a same-origin route so the browser never talks to a second host.
  4. Offline without conflicts. New expenses queue and replay; edits and settlements need a connection. We chose fewer features over a CRDT.
  5. Realtime that leaks nothing. SSE sends "something changed", the client refetches. The stream itself carries no room data.
  6. No egress in prod. Containers can't reach the internet; push, FX and the receipt model go through an allowlisted proxy.

The catch, written down

Split is free with no paid tier and is top-of-funnel for Peanut, a payments app. We wrote the limits into STEWARDSHIP.md: no nags, no modals, no preselected payment option, no feature gates. AGPL so a hosted fork stays open.

Repo: https://github.com/peanutprotocol/peanutsplit · Try it: https://peanutsplit.com

Top comments (0)