Skip to content
vishesh-varmaPublic

About

FairShare — a free, cross-platform expense-splitting app and a more generous Splitwise alternative. Flutter (iOS, Android, web) + Firebase. Offline-first, multi-currency, unlimited expenses. Tracks who owes whom across personal balances and groups; no payments. Server-side balance math via Cloud Functions.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

FairShare

A free expense-splitting web app — a more generous Splitwise alternative. Flutter web + Firebase. Multi-currency, unlimited expenses. Tracks who owes whom across personal balances and groups; it does not move money.


Architecture in one paragraph

The expense ledger is the source of truth. A Cloud Function recomputes a per-group balances summary on every expense write — and is the only writer of that summary (security rules forbid clients from writing it), which keeps the debt graph tamper-proof. Clients read the cheap summary for display. Simplify Debts runs client-side, display-only, and never mutates data. Money is stored in each expense's original currency + a pivot rate (→USD) captured at entry time; original amounts are never mutated, so single-currency users see exact figures and only blended cross-currency totals incur (acknowledged) rounding.

See docs/DATA_MODEL.md for the full Firestore layout.


Developing in the Dev Container

Works the same whether the container is opened via GitHub Codespaces or locally (VS Code Dev Containers on Docker Desktop / WSL2). The dev container (.devcontainer/) auto-installs Flutter (stable, web only), the Firebase CLI, a JRE for the emulators, and Node, then pre-downloads the emulators. That takes a few minutes on first create. The emulators auto-start on every container start (postStartCommand), with data persisted in emulator-data/ so test accounts survive restarts.

Daily workflow — two commands

./scripts/web.sh                          # run the app (forwarded port 3000)
(cd functions && npm run build:watch)     # only while editing Cloud Functions

Open the forwarded port 3000 in your browser. Debug builds auto-connect to the emulators; the Emulator Suite UI is on port 4000.

Google sign-in in development goes through the Auth emulator, which fakes the account chooser — no real OAuth setup, no google-services.json, no client IDs.

If sign-in hangs

A popup that opens but never loads means the emulators aren't running (they should have auto-started). Check /tmp/emulators.log, or start them by hand:

./scripts/emulators.sh

The app also preflights the Auth emulator before opening the popup and shows a clear error instead of hanging (see auth_service.dart).

Tests

flutter test

Project layout

.devcontainer/        Dev container image + auto-setup + emulator auto-start
functions/            Cloud Functions (TypeScript) — balance pipeline
lib/
  firebase_bootstrap.dart   Firebase init; auto-wires emulators in debug
  firebase_options.dart     Web Firebase config (public identifiers, not secrets)
  auth_service.dart         Google sign-in via signInWithPopup + profile doc
scripts/
  web.sh              Run the web app on port 3000
  emulators.sh        Start emulators with data persistence
firestore.rules       DEFAULT-DENY security rules (balances doc client-locked)
firebase.json         Emulator ports + rules/functions/hosting wiring
docs/DATA_MODEL.md    Firestore collection structure

Android/iOS were deliberately dropped — this is a web app. If you ever revive them, start from git log (the android/ tree and its docs were removed in the "web-only" cleanup commit).


Security rules — do not weaken

Rules are default-deny. The single most important invariant: clients can read groups/{id}/balances/* but can never write it. Only the Cloud Function (admin SDK) writes balances. Test rule changes against the emulator before deploying.

Deploying

flutter build web
firebase deploy            # hosting + functions + rules

Deploying to real Firebase (not the emulator) is the point where Google sign-in needs real OAuth: enable the Google provider in Firebase console → Authentication → Sign-in method, and add your hosting domain to the authorized domains list. Nothing in the app code changes.

About

FairShare — a free, cross-platform expense-splitting app and a more generous Splitwise alternative. Flutter (iOS, Android, web) + Firebase. Offline-first, multi-currency, unlimited expenses. Tracks who owes whom across personal balances and groups; no payments. Server-side balance math via Cloud Functions.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages