Open-source bill splitting
A private, local-first app for shared expenses, built in public and open to new ideas and contributors.
Open PartageMade for real groups
Partage helps friends, families, and roommates keep track of who paid for what and settle up, without making everyone create another account. The hosted app is free, has no ads or individual tracking, and works offline. The short product tour shows what using it looks like.
The first prototype was written in JavaScript. As the rules around splits, history, and offline edits grew, I restarted it in Elm. For an app that keeps track of people’s shared expenses, I wanted the domain to be boring in the best way: explicit, deterministic, and easy to test.
How the pieces fit together
The frontend is Elm 0.19.1, with the interface built in elm-ui 2.0. The browser is not a thin client: each device keeps the group’s encrypted history in IndexedDB, works from that local copy, and synchronizes when a connection is available.
- The domain is a fold. A group is an append-only log of signed events.
Domain.GroupState.applyEventsreplays that log into the current members, entries, balances, settlement plan, and activity. Devices with the same valid events derive the same state, so offline edits converge without a server-side merge. - Effects stay at the edges. Web Crypto, IndexedDB, HTTP, and compression flow through typed
elm-concurrent-tasktasks insrc/Infra, backed by small vendored browser bindings.public/index.jscontains the remaining startup and custom-element glue rather than domain logic. - The relay is deliberately small. The Hono application stores opaque encrypted records in SQLite and tells connected clients when new records arrive. Clients remain the source of truth and can restore history that the relay has lost.
This split keeps the business rules pure and testable while the replaceable edges handle browsers, storage, and transport. The README architecture overview is a good map before going deeper.
Use it on your terms
The app and relay live in one public GitHub repository. The Elm PWA, including the local ledger and browser-side encryption, is licensed under MPL-2.0. The Node, Hono, and SQLite relay has its own Apache-2.0 licence.
The standard self-hosted deployment puts the static PWA and relay in one container and keeps SQLite on a persistent volume. Push notifications and the feedback form are optional. The deployment guide covers builds, configuration, backups, reverse proxies, quotas, retention, and the operator dashboard.
There are several ways in
You do not need to understand the whole synchronization protocol before helping. Useful contributions can start in many places:
- try the app on a browser or device I may have missed, and report confusing behaviour, accessibility gaps, or PWA rough edges;
- work on the Elm domain, the
elm-uiinterface, or the tests that connect them; - review the cryptography, event replay, relay boundary, or self-hosting documentation; or
- translate Partage into another language, or improve the documentation and existing English or French wording.
I currently maintain Partage, so a precise question or a small focused contribution is genuinely useful; it does not have to arrive as a finished redesign. The README gets the local stack running, CI checks formatting, elm-review, and the test suites, and bugs, questions, and pull requests are welcome in the issue tracker.
Open, with clear limits
Publishing code does not make a privacy claim true by itself, but it makes the boundary inspectable. The encryption page documents what the relay can still observe and the limits of a web app. The no-account page explains device identity and recovery.
The canonical specification records the intended behaviour and security boundaries. The cryptographic design has not been independently audited, and an operator serving modified web code could read data entered through that version of the app. If threat modelling is your thing, careful criticism here is especially welcome.