Skip to content

gazarrillo/bloc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

99 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Bloc

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

Why Bloc

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.

Stack

  • Frontend — React 18 + Vite + TypeScript + Tailwind CSS
  • Backend — Firebase (Auth, Firestore, Cloud Functions, Hosting)
  • Mobile — Capacitor (iOS + Android wrappers around the web build)
  • i18nreact-i18next, Spanish default, English supported
  • PWA — installable on mobile and desktop

Quick start

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 dev

You'll need your own Firebase project:

  1. Create one at console.firebase.google.com.
  2. Enable Authentication (Google + email/password), Firestore, Functions, and Hosting.
  3. Copy the web app config into .env.local.
  4. Update .firebaserc to point at your project ID (the committed value bloc-app-ve is the maintainer's project — override locally; don't commit your change unless you're forking).
  5. Deploy Firestore rules and indexes: firebase deploy --only firestore.

Scripts

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, hosting

Single test file:

npx vitest run src/lib/__tests__/balances.test.ts

Firebase emulators

Set VITE_USE_EMULATORS=true in .env.local, then:

firebase emulators:start

Ports: Auth 9099, Firestore 8080, Functions 5001, UI 4000.

Mobile (Capacitor)

npm run cap:sync     # Build + sync to native projects
npm run cap:ios      # ... + open Xcode
npm run cap:android  # ... + open Android Studio

Native 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.

Architecture

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 exchangeRateSnapshot stored on each expense, not live rates.
  • Cloud Functions (functions/) scrape exchange rates from ve.dolarapi.com / yadio.io into the exchangeRates Firestore collection.
  • Pending slots let you split an EQUAL expense with people who haven't joined the group yet; shares rebalance automatically when they join.

Contributing

PRs welcome. See CONTRIBUTING.md for branch conventions, the PR checklist, and the i18n rule (every user-facing string needs both es and en).

Security

Found a vulnerability? Please report privately — see SECURITY.md. Don't open a public issue.

License

MIT © Giovanni Zarrillo

About

Venezuela-tailored expense splitting app — multi-currency (USD/VES/USDT), WhatsApp-first invites, Spanish-default.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors