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/PROJECT.md — architecture, domains, balance & budget semantics
- docs/AGENTS.md — playbook for AI agents (where to edit, pitfalls, feature checklist)
- Flask MVC + SQLAlchemy + Flask-Login
- Postgres (Supabase)
- Drop all existing tables in Supabase (fresh schema), or on an existing DB run:
scripts/add_indexes.sqlscripts/add_monthly_budget.sql(addsusers.monthly_budget)scripts/add_user_theme.sql(addsusers.theme_mode,users.theme_accent)
- Copy
.env.exampleto.envand fill in values (prefer Supabase pooler URL on port6543). pip install -r requirements.txt- Set
FLASK_ENV=developmentlocally, thenpython run.py— creates tables and seeds admin fromADMIN_USERNAME/ADMIN_PASSWORD. - On Vercel: omit
FLASK_ENV(or set production) so cold starts skipcreate_all/ seed. Run SQL scripts manually for schema changes.
- Login as admin at http://localhost:5000/login (or register a new account).
- Add People (manoj, akshay, baba, etc.).
- Create Groups (e.g. "Roommates") by selecting members.
- Add expenses — use Quick select group to auto-check participants.
- View Itemized report and Balances.
| 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 |
/register— open sign-up; each user gets isolated people, groups, expenses/login— session login; stays signed in forSESSION_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)
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), plustheme_mode/theme_accentwhen set- Period (optional on bootstrap / expenses / settlements / balances / report; omit = all time):
year=2026&month=8— calendar monthfrom=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 expenseGET /api/expenses,/api/settlements,/api/balances,/api/report?filter=all|shared|personalGET /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 }(nullor0clears)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 browserlocalStoragekeyswmini.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.
GET /admin/usersPOST /admin/users/<id>/togglePOST /admin/users/<id>/password— body{ "password": "..." }(min 4 chars; non-admin users only)DELETE /admin/users/<id>
User model includes role, is_active, created_at, monthly_budget, theme_mode, theme_accent. No payment features yet.