Skip to content

Repository files navigation

Splitwise Mini

Multi-user expense tracker by Manoj Hankare (manojhankare.in): shared bills with groups, personal spending, itemized reports, monthly budget, and per-user isolated data.

Docs

  • docs/PROJECT.md — architecture, domains, balance & budget semantics
  • docs/AGENTS.md — playbook for AI agents (where to edit, pitfalls, feature checklist)

Stack

  • Flask MVC + SQLAlchemy + Flask-Login
  • Postgres (Supabase)

Setup

  1. Drop all existing tables in Supabase (fresh schema), or on an existing DB run:
    • scripts/add_indexes.sql
    • scripts/add_monthly_budget.sql (adds users.monthly_budget)
    • scripts/add_user_theme.sql (adds users.theme_mode, users.theme_accent)
  2. Copy .env.example to .env and fill in values (prefer Supabase pooler URL on port 6543).
  3. pip install -r requirements.txt
  4. Set FLASK_ENV=development locally, then python run.py — creates tables and seeds admin from ADMIN_USERNAME / ADMIN_PASSWORD.
  5. On Vercel: omit FLASK_ENV (or set production) so cold starts skip create_all / seed. Run SQL scripts manually for schema changes.

First use

  1. Login as admin at http://localhost:5000/login (or register a new account).
  2. Add People (manoj, akshay, baba, etc.).
  3. Create Groups (e.g. "Roommates") by selecting members.
  4. Add expenses — use Quick select group to auto-check participants.
  5. View Itemized report and Balances.

Environment variables

Variable Description
DATABASE_URL Postgres connection string (pooler :6543 recommended on Vercel)
SECRET_KEY Flask session secret (required)
SESSION_DAYS Stay signed in this many days after login/register (default 30, max 365)
ADMIN_USERNAME Initial admin username (seeded once in development)
ADMIN_PASSWORD Initial admin password
FLASK_ENV Set to development locally to create tables + seed on startup
ENABLE_DB_CREATE Set to 1 to force schema create without FLASK_ENV=development

Auth

  • /register — open sign-up; each user gets isolated people, groups, expenses
  • /login — session login; stays signed in for SESSION_DAYS (default 30) via permanent session + remember cookie (survives browser restart until expiry or Log out)
  • /admin — admin dashboard (user list, enable/disable, set password, delete)

API (all require login)

  • GET /api/bootstrap?filter=all|shared|personal — people, groups, expenses, settlements, balances, report, plus monthly budget fields (monthly_budget, budget_spent, budget_personal, budget_my_shared, budget_shared_total) for the current UTC month (independent of period filters), plus theme_mode / theme_accent when set
  • Period (optional on bootstrap / expenses / settlements / balances / report; omit = all time):
    • year=2026&month=8 — calendar month
    • from=2026-08-01&to=2026-08-31 — inclusive range (wins if both styles sent)
  • GET/POST /api/people, DELETE /api/people/<id>
  • GET/POST /api/groups, PUT/DELETE /api/groups/<id>
  • POST /api/add — structured body:
    {
      "description": "food jay malhar",
      "amount": 240,
      "payer": "manoj",
      "participants": ["manoj", "baba", "akshay"],
      "is_personal": false,
      "date": "2026-07-03"
    }
  • PUT /api/expenses/<id> — same body as add; update an existing expense
  • GET /api/expenses, /api/settlements, /api/balances, /api/report?filter=all|shared|personal
  • GET /api/expenses/<id>/outstanding — full outstanding for settle (not period-scoped)
  • POST /api/settlements, DELETE /api/settlements/<id>
  • DELETE /api/delete/<id>
  • GET /api/settings/budget{ "monthly_budget": 2000 | null }
  • PUT /api/settings/budget — body { "monthly_budget": 2000 } (null or 0 clears)
  • GET /api/settings/theme{ "theme_mode": "light"|"dark"|null, "theme_accent": "indigo"|...|null }
  • PUT /api/settings/theme — body { "theme_mode": "light"|"dark", "theme_accent": "indigo"|"teal"|"rose"|"amber"|"slate" } (also mirrored in browser localStorage key swmini.theme)

UI defaults Report/Balances to the current local month via period params; people/groups and mutations stay unscoped. Budget progress always uses the current UTC month.

Admin API

  • GET /admin/users
  • POST /admin/users/<id>/toggle
  • POST /admin/users/<id>/password — body { "password": "..." } (min 4 chars; non-admin users only)
  • DELETE /admin/users/<id>

SaaS notes

User model includes role, is_active, created_at, monthly_budget, theme_mode, theme_accent. No payment features yet.

About

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages