Expense splitting for Venezuela. Multi-currency (USD / VES / USDT), WhatsApp-first invites, Spanish by default, exchange-rate snapshots so historical balances stay accurate across VES volatility.
Live app: getbloc.web.app
Standard expense-splitting apps don't handle Venezuela's reality: people pay in dollars, get paid in bolívares, settle in USDT, and the BCV exchange rate moves daily. Bloc is built around that — every expense stores the rate snapshot used at write time, so a balance from three months ago still reconciles correctly today.
- Frontend — React 18 + Vite + TypeScript + Tailwind CSS
- Backend — Firebase (Auth, Firestore, Cloud Functions, Hosting)
- Mobile — Capacitor (iOS + Android wrappers around the web build)
- i18n —
react-i18next, Spanish default, English supported - PWA — installable on mobile and desktop
git clone https://github.com/gazarrillo/bloc.git
cd bloc
npm install
cp .env.example .env.local
# fill in your own Firebase project config in .env.local
npm run devYou'll need your own Firebase project:
- Create one at console.firebase.google.com.
- Enable Authentication (Google + email/password), Firestore, Functions, and Hosting.
- Copy the web app config into
.env.local. - Update .firebaserc to point at your project ID (the committed value
bloc-app-veis the maintainer's project — override locally; don't commit your change unless you're forking). - Deploy Firestore rules and indexes:
firebase deploy --only firestore.
npm run dev # Vite dev server
npm run build # Type-check + production build
npm run typecheck # tsc --noEmit
npm run test # Vitest once
npm run test:watch # Vitest in watch mode
npm run deploy # Build + deploy hosting
npm run deploy:all # Build + deploy firestore, functions, hostingSingle test file:
npx vitest run src/lib/__tests__/balances.test.tsSet VITE_USE_EMULATORS=true in .env.local, then:
firebase emulators:startPorts: Auth 9099, Firestore 8080, Functions 5001, UI 4000.
npm run cap:sync # Build + sync to native projects
npm run cap:ios # ... + open Xcode
npm run cap:android # ... + open Android StudioNative projects live in ios/ and android/. The committed google-services.json and GoogleService-Info.plist are Firebase client config (designed to be public); security is enforced by Firestore rules and App Check, not by hiding them.
A condensed architecture cheat sheet lives in CLAUDE.md. Highlights:
- All Firestore CRUD goes through src/firebase/service.ts.
- Data fetching is in src/hooks/ — no global state manager.
- Balance math is in src/lib/balances.ts; the critical invariant is that balances use the
exchangeRateSnapshotstored on each expense, not live rates. - Cloud Functions (functions/) scrape exchange rates from
ve.dolarapi.com/yadio.iointo theexchangeRatesFirestore collection. - Pending slots let you split an EQUAL expense with people who haven't joined the group yet; shares rebalance automatically when they join.
PRs welcome. See CONTRIBUTING.md for branch conventions, the PR checklist, and the i18n rule (every user-facing string needs both es and en).
Found a vulnerability? Please report privately — see SECURITY.md. Don't open a public issue.
MIT © Giovanni Zarrillo