One-tap meals ยท Auto meal rates ยท Transparent finances ยท PDF reports
No more paper khatas. No more accusations. Just math. โจ
Every university mess in Bangladesh runs on WhatsApp groups, paper khatas, and mental math. Managers get accused of stealing money, members forget which meals they ate, and month-end calculations take hours.
| ๐ฑ WhatsApp Groups | ๐ Paper Khatas | ๐งฎ Mental Math | |
|---|---|---|---|
| ๐ฉ | "เฆญเฆพเฆ เฆเฆเฆเง เฆเฆพเฆฌเง เฆจเฆพ" | เฆนเฆพเฆฐเฆฟเฆฏเฆผเง เฆเงเฆเง | "เฆฎเฆจเง เฆจเฆพเฆ เฆญเฆพเฆ" |
| ๐ค | "เฆเง เฆฌเฆพเฆเฆพเฆฐ เฆเฆฐเฆฌเง?" | เฆญเงเฆฒ เฆนเฆฟเฆธเฆพเฆฌ | "เฆคเงเฆฎเฆพเฆฐ เงซเงฆ เฆเฆพเฆเฆพ เฆฌเฆพเฆเฆฟ" |
| ๐คฌ | "เฆฎเงเฆฏเฆพเฆจเงเฆเฆพเฆฐ เฆเฆพเฆเฆพ เฆฎเฆพเฆฐเฆเง!" | เฆเงเฆเฆกเฆผเฆพ เฆชเงเฆ | "เฆเฆฎเฆฟ เงจ เฆฌเงเฆฒเฆพเฆ เฆเฆพเฆเฆจเฆฟ!" |
โฌ๏ธ
| Feature | What it does | Vibe | |
|---|---|---|---|
| ๐ฝ๏ธ | Meal Tracking | Toggle breakfast/lunch/dinner with one tap | "เฆเฆเฆเง เฆฒเฆพเฆเงเฆ เฆ เฆซ" |
| ๐ | Bazaar Logs | Record every shopping trip item-by-item | "เฆเฆ เฆชเงเฆเฆฏเฆผเฆพเฆ เงง เฆเงเฆเฆฟ, เงชเงฆ เฆเฆพเฆเฆพ" |
| ๐ | Auto Meal Rate | Total Bazaar รท Total Meals = Rate โ live |
"เฆเฆเฆเงเฆฐ เฆฐเงเฆ เงฉเงฎ.เงซเงฆ" |
| ๐ฐ | Deposits | Track every taka deposited, with approval | "เงงเงซเงฆเงฆ เฆฌเฆฟเฆเฆพเฆถเง เฆฆเฆฟเฆฒเฆพเฆฎ" |
| ๐ | PDF Reports | One-click export for any member or full mess | "เฆเฆ เฆจเฆพเฆ PDF" |
| ๐ | Spending Charts | Visualize who ate how much with bar charts | "เฆธเฆฌเฆเงเฆฏเฆผเง เฆฌเงเฆถเฆฟ เฆคเงเฆฎเฆฟ เฆเฆพเฆ เฆญเฆพเฆ" |
| ๐ฅ | Manager Tools | Month closing, member management, role transfer | "เฆจเฆคเงเฆจ เฆฎเงเฆฏเฆพเฆจเงเฆเฆพเฆฐ เฆจเฆฟเฆฏเงเฆเงเฆค" |
| โฐ | Cutoff Locking | Auto-lock meals after configurable cutoff times | "เฆฐเฆพเฆค เงฏเฆเฆพเฆฐ เฆชเฆฐ เฆฌเฆจเงเฆง" |
| ๐ | Full Auth | Email/password + Google OAuth + password reset | "เฆญเงเฆฒเง เฆเงเฆเฆฟ? Reset!" |
| ๐ฑ | PWA Ready | Install on home screen, works like native app | "เฆ เงเฆฏเฆพเฆช เฆเฆฐ เฆฎเฆคเงเฆ!" |
graph TB
subgraph Client ["๐ฅ๏ธ Client Layer"]
A["โ๏ธ React 19 + Next.js 16<br/><i>App Router + Turbopack</i>"]
B["๐จ Tailwind CSS v4 + shadcn/ui"]
C["๐ Recharts + jsPDF"]
end
subgraph Server ["โ๏ธ Server Layer"]
D["๐ Server Actions<br/><i>Type-safe RPC</i>"]
E["๐ก๏ธ Auth Middleware<br/><i>Protected Routes</i>"]
F["๐๏ธ React Query<br/><i>Smart Caching</i>"]
end
subgraph Database ["๐๏ธ Supabase (PostgreSQL)"]
G["๐ 14 Tables<br/><i>3NF Normalized</i>"]
H["๐ Row Level Security<br/><i>Per-mess isolation</i>"]
I["โก Triggers & RPCs<br/><i>Atomic operations</i>"]
end
A --> D
B --> A
C --> A
D --> E
E --> G
F --> D
G --> H
G --> I
style Client fill:#1a1a2e,stroke:#FF6B6B,color:#fff
style Server fill:#16213e,stroke:#FFA94D,color:#fff
style Database fill:#0f3460,stroke:#3FCF8E,color:#fff
๐ Click to expand Entity Relationship Diagram
erDiagram
profiles ||--o{ mess_members : "has membership"
profiles ||--o{ messes : "creates"
messes ||--o{ mess_members : "has"
messes ||--o{ mess_cycles : "has"
messes ||--o{ bazaar_expenses : "has"
messes ||--o{ fixed_costs : "has"
messes ||--o{ individual_costs : "has"
messes ||--o{ inventory : "tracks"
messes ||--o{ meal_cutoff_config : "configures"
messes ||--o{ activity_log : "logs"
messes ||--o{ announcements : "posts"
mess_cycles ||--o{ daily_meals : "contains"
mess_cycles ||--o{ transactions : "records"
mess_cycles ||--o{ bazaar_expenses : "tracks"
mess_cycles ||--o{ fixed_costs : "includes"
mess_cycles ||--o{ individual_costs : "includes"
mess_cycles ||--o{ month_snapshots : "archives"
mess_members ||--o{ daily_meals : "logs"
mess_members ||--o{ transactions : "makes"
mess_members ||--o{ individual_costs : "incurs"
bazaar_expenses ||--o{ bazaar_items : "contains"
profiles {
uuid id PK
text full_name
text email
text phone
text avatar_url
}
messes {
uuid id PK
text name
text address
uuid created_by FK
text invite_code
int max_members
}
mess_members {
uuid id PK
uuid mess_id FK
uuid user_id FK
user_role role
user_status status
date join_date
date leave_date
}
mess_cycles {
uuid id PK
uuid mess_id FK
text name
date start_date
date end_date
cycle_status status
numeric final_meal_rate
}
daily_meals {
uuid id PK
uuid mess_id FK
uuid cycle_id FK
uuid member_id FK
date meal_date
boolean breakfast
boolean lunch
boolean dinner
int guest_breakfast
int guest_lunch
int guest_dinner
}
transactions {
uuid id PK
uuid mess_id FK
uuid cycle_id FK
uuid member_id FK
numeric amount
payment_method method
text reference_no
}
bazaar_expenses {
uuid id PK
uuid mess_id FK
uuid cycle_id FK
uuid shopper_id FK
date expense_date
numeric total_amount
}
bazaar_items {
uuid id PK
uuid expense_id FK
text item_name
numeric quantity
text unit
numeric unit_price
numeric total_price
}
fixed_costs {
uuid id PK
uuid mess_id FK
uuid cycle_id FK
fixed_cost_type cost_type
numeric amount
}
individual_costs {
uuid id PK
uuid mess_id FK
uuid cycle_id FK
uuid member_id FK
text description
numeric amount
approval_status status
}
inventory {
uuid id PK
uuid mess_id FK
text item_name
numeric current_qty
text unit
}
month_snapshots {
uuid id PK
uuid cycle_id FK
uuid member_id FK
int total_meals
numeric meal_rate
numeric closing_balance
}
meal_cutoff_config {
uuid id PK
uuid mess_id FK
time breakfast_cutoff
time lunch_cutoff
time dinner_cutoff
}
activity_log {
uuid id PK
uuid mess_id FK
uuid actor_id FK
text action
jsonb details
}
announcements {
uuid id PK
uuid mess_id FK
text title
text content
text priority
}
graph LR
A["๐ต Opening Balance<br/><i>from previous month</i>"] --> E
B["โ Deposits<br/><i>cash, bKash, Nagad</i>"] --> E
E["๐ Credits"] --> F
C1["๐ฝ๏ธ Meals ร Rate"] --> G
C2["๐ Prorated Fixed Costs<br/><i>rent, gas, wifi...</i>"] --> G
C3["๐ค Individual Costs"] --> G
G["๐ Debits"] --> F
F["๐ฐ Current Balance<br/><i>= Credits - Debits</i>"]
style A fill:#22c55e,stroke:#16a34a,color:#fff
style B fill:#22c55e,stroke:#16a34a,color:#fff
style E fill:#3b82f6,stroke:#2563eb,color:#fff
style C1 fill:#ef4444,stroke:#dc2626,color:#fff
style C2 fill:#ef4444,stroke:#dc2626,color:#fff
style C3 fill:#ef4444,stroke:#dc2626,color:#fff
style G fill:#f97316,stroke:#ea580c,color:#fff
style F fill:#8b5cf6,stroke:#7c3aed,color:#fff
Balance = (Opening + Deposits) โ (Meals ร Rate + Fixed Costs + Individual Costs)
sequenceDiagram
participant M as ๐ค Manager
participant S as โ๏ธ Server Action
participant DB as ๐๏ธ PostgreSQL
M->>S: Click "Close Month"
S->>DB: BEGIN TRANSACTION
Note over DB: ๐ Lock cycle row (FOR UPDATE)
DB->>DB: Calculate final meal rate
DB->>DB: Snapshot every member's balance
DB->>DB: Archive current cycle โ 'closed'
DB->>DB: Create next month's cycle
DB->>DB: Log activity
DB->>S: COMMIT โ Return new_cycle_id
S->>M: โ
"Month closed successfully!"
Note over M,DB: ๐ All atomic โ if anything<br/>fails, everything rolls back!
| Layer | Technology | Why |
|---|---|---|
| โ๏ธ Frontend | Next.js 16 + React 19 | App Router, Server Actions, Turbopack |
| ๐จ Styling | Tailwind CSS v4 + shadcn/ui | Beautiful, consistent, accessible |
| ๐๏ธ Database | Supabase (PostgreSQL) | RLS, Triggers, RPCs, Realtime |
| ๐ Auth | Supabase Auth | Email/Password + Google OAuth |
| ๐ Charts | Recharts | Interactive, responsive visualizations |
| ๐ PDF | jsPDF + AutoTable | Generate reports client-side |
| ๐ฆ State | React Query (TanStack) | Smart caching, auto-refetch |
| โ Validation | Zod | Runtime type safety |
| ๐ Deploy | Vercel | Zero-config, edge-optimized |
| ๐ฑ PWA | Web Manifest | Installable, native-like |
kangal-app/
โโโ ๐ public/
โ โโโ manifest.json # PWA configuration
โ โโโ icons/ # App icons (192ร192, 512ร512)
โ
โโโ ๐ฆ src/
โ โโโ ๐๏ธ app/
โ โ โโโ (auth)/ # ๐ Login, Signup, Forgot Password
โ โ โโโ auth/callback/ # ๐ OAuth callback handler
โ โ โโโ dashboard/ # ๐ Main app
โ โ โ โโโ page.tsx # ๐ Dashboard overview
โ โ โ โโโ meals/ # ๐ฝ๏ธ Meal toggles + chart + manage
โ โ โ โโโ bazaar/ # ๐ Bazaar expense logs
โ โ โ โโโ deposits/ # ๐ฐ Deposit management
โ โ โ โโโ options/ # โ๏ธ Cycle & mess settings
โ โ โ โโโ settings/ # ๐ค User profile settings
โ โ โ โโโ admin/ # ๐ Manager-only
โ โ โ โโโ costs/ # ๐ธ Fixed & individual costs
โ โ โ โโโ members/ # ๐ฅ Member management
โ โ โ โโโ month-close/ # ๐ Monthly settlement
โ โ โโโ page.tsx # ๐ Landing page (marketing)
โ โ
โ โโโ ๐งฉ components/
โ โ โโโ dashboard/ # Stats cards, charts, meal toggles
โ โ โโโ landing/ # Animated hero, feature cards
โ โ โโโ mess-context.tsx # ๐ Shared context (perf optimization)
โ โ โโโ ui/ # shadcn/ui primitives
โ โ
โ โโโ ๐ lib/
โ โ โโโ actions/ # Server actions (meals, bazaar, finance)
โ โ โโโ supabase/ # Client & middleware setup
โ โ โโโ pdf-export.ts # PDF generation logic
โ โ โโโ validations.ts # Zod schemas
โ โ
โ โโโ ๐ types/ # TypeScript type definitions
โ
โโโ ๐๏ธ supabase/
โโโ schema.sql # Complete DB schema (14 tables, RLS, triggers)
โโโ migration_fixes.sql # Post-deploy fixes
โโโ migration_approval_system.sql # Approval workflow
graph TD
subgraph Auth ["๐ Authentication"]
A1["Supabase Auth<br/><i>JWT Tokens</i>"]
A2["Next.js Middleware<br/><i>Route Protection</i>"]
end
subgraph RLS ["๐ก๏ธ Row Level Security"]
R1["is_mess_member()"]
R2["is_mess_manager()"]
end
subgraph Policies ["๐ Access Policies"]
P1["Members โ own mess data only"]
P2["Managers โ full CRUD"]
P3["Cross-mess โ impossible"]
end
A1 --> A2
A2 --> R1
A2 --> R2
R1 --> P1
R2 --> P2
R1 --> P3
style Auth fill:#1a1a2e,stroke:#FF6B6B,color:#fff
style RLS fill:#16213e,stroke:#FFA94D,color:#fff
style Policies fill:#0f3460,stroke:#3FCF8E,color:#fff
- Every table has RLS enabled โ no data leaks between messes
- Server-side auth via Supabase SSR middleware
- No secrets in client โ all sensitive operations are Server Actions
- Atomic transactions โ month closing uses
SECURITY DEFINERRPCs
- Node.js 18+ and npm
- A Supabase project (free tier works!)
# 1๏ธโฃ Clone the repo
git clone https://github.com/sovon1/kangal-app.git
cd kangal-app
# 2๏ธโฃ Install dependencies
npm install
# 3๏ธโฃ Set up environment variables
cp .env.local.example .env.local
# Edit .env.local with your Supabase URL and anon key
# 4๏ธโฃ Set up the database
# Copy supabase/schema.sql โ Supabase SQL Editor โ Run
# 5๏ธโฃ Start the dev server
npm run devOpen http://localhost:3000 and you're live! ๐
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Your Supabase anonymous key |
๐ฑ Open kangal.software on your phone
โ
๐ฅ Tap "Add to Home Screen"
โ
๐ Done! Works like a native app!
| Function | Purpose |
|---|---|
calculate_meal_rate(cycle_id) |
ฮฃ Bazaar รท ฮฃ Meals โ the core formula |
prorate_fixed_costs(member_id, cycle_id) |
Fair share based on days present |
calculate_member_balance(member_id, cycle_id) |
Full financial breakdown |
close_mess_month(cycle_id) |
Atomic month close (snapshot โ archive โ new cycle) |
enforce_meal_cutoff() |
Trigger: blocks meal changes after cutoff (managers bypass) |
deduct_inventory_on_bazaar() |
Auto-updates inventory on bazaar entry |
update_bazaar_total() |
Auto-recalculates expense totals |
user_role โ 'manager' | 'member' | 'cook'
user_status โ 'active' | 'inactive' | 'on_leave'
payment_method โ 'cash' | 'bkash' | 'nagad' | 'bank_transfer' | 'other'
approval_status โ 'pending' | 'approved' | 'rejected'
cycle_status โ 'open' | 'closed' | 'archived'
fixed_cost_type โ 'cook_salary' | 'wifi' | 'gas' | 'electricity' | 'water' | 'rent' | ...Contributions are welcome! Feel free to:
- ๐ด Fork the repo
- ๐ฟ Create a branch (
git checkout -b feature/amazing-feature) - ๐พ Commit changes (
git commit -m 'Add amazing feature') - ๐ค Push (
git push origin feature/amazing-feature) - ๐ Open a Pull Request
This project is open source under the MIT License.