Splitr — Split Everything You Can Imagine & Get Rewarded

Inspiration

Managing shared expenses with roommates and friends is repetitive and error-prone — splitting totals, tracking who paid, chasing late payments, and keeping a tally of shared credits felt like avoidable friction. Splitr was inspired by the need for a lightweight, trustworthy workflow that makes splitting fair, transparent, and rewarding.

What it does

  • Create bills, split amounts among participants, invite friends to pay, and track payment status (open / partially paid / paid).
  • Automatically credit payers for on-time payments and show users a redeemable credit balance.
  • Simple auth-backed UX: signup / login (Supabase) → dashboard → bills / friends → payments / redeem.
  • Built-in dev mock for card/processor flows so you can demo payments without a real gateway (backend mock bank).

Key flows:

  • Create bill → backend records bill + participants (transactional).
  • Participant pays → payment recorded, participant marked paid, credits added and logged.
  • Redeem credits → credits consumed and redemptions logged.

(See frontend pages: page.tsx, bills flow: frontend/app/bills/page.tsx.)

How we built it

  • Frontend: Next.js (App Router), TypeScript, Tailwind CSS, Framer Motion. Supabase JS SDK for auth and client queries. Key code: supabaseClient.ts.
  • Backend: FastAPI + Uvicorn; small service layer that delegates DB ops to Supabase client. Key entrypoints: main.py and reward/account helpers in reward.py.
  • Database & Auth: Supabase (Postgres + Auth) is the single source of truth for profiles, bills, participants, payments, and credit_log.
  • Local dev: .env/.env.local configure Supabase and local mock bank; mock bank code under backend for demos.

Architecture summary:

  • Frontend uses Supabase for auth and queries, and calls backend endpoints for protected business logic (payments, reward issuance) to avoid client-side manipulation.
  • Backend uses Supabase server client to perform transactional operations (create bill + participants + ledger entries) and to keep reward logic authoritative.

Challenges we ran into

  • Supabase join shapes sometimes return nested arrays for joined rows; required defensive normalization in frontend queries to avoid runtime errors.
  • Local dev HTTPS / CORS caused browser warnings; added TLS options and documented mkcert/ngrok workflows.
  • Repo clutter: multiple one-off scripts and legacy helpers required reorganization and conservative cleanup tooling.
  • Payment integration complexity (idempotency, webhooks, reconciliation) was scoped down; we used a mock bank for reliable demos.

Accomplishments that we're proud of

  • End-to-end demoable flows: signup/login → create bill → split & invite → pay via mock bank → credits issued → redeem.
  • Reorganized backend into focused routers/services and added safe cleanup utilities for test data.
  • Clean Next.js app-router UX with a client-side Layout component and protected dashboard pages.
  • Implemented enriched credit history UI that computes reward multipliers and reasons for entries.

What we learned

  • Next.js app-router: server vs client components, usePathname rules, and proper placement of client-only logic.
  • Supabase practicalities: careful handling of joined row shapes, choosing when to use client SDK vs server-side service keys.
  • Importance of server-side reward/payment logic (prevent client manipulation) and atomic DB operations for multi-row workflows.
  • Local dev tooling (mkcert/ngrok) is essential for realistic testing with HTTPS.

What's next for Splitr

  • Add DB migrations (Alembic / Supabase migrations) and canonical schema.
  • Replace mock bank with a real payment provider (Stripe/other) with idempotency and secure webhook handling.
  • Add background workers for async tasks (email notifications, reconciliation) and broaden test coverage (backend pytest + frontend testing-library + Playwright).
  • Harden ops & security: secrets in CI, Sentry for errors, metrics, staging environment.

Built With

Share this project:

Updates