尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證kotasa by VIMMIK - Share it. Settle it.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Share it. Settle it. Shared expenses for offices, friends, trips and families. Anyone pays, Kotasa keeps count, and everyone settles once a week. කොටස (kotasa) means "a share" in Sinhala. In most offices and friend groups, one person buys lunch, another pays for the Uber, someone else picks up the birthday cake. By Friday nobody remembers who owes whom.檢視完整 README ↗
Share it. Settle it.
Shared expenses for offices, friends, trips and families. Anyone pays, Kotasa keeps count, and everyone settles once a week.
කොටස (kotasa) means "a share" in Sinhala.
In most offices and friend groups, one person buys lunch, another pays for the Uber, someone else picks up the birthday cake. By Friday nobody remembers who owes whom.
Kotasa writes every shared cost down, splits it fairly, and nets it into one clear amount per person. Each week, everyone gets an SMS with their total and a link that shows exactly where each rupee came from, whether or not they use the app.
| Benefit | What it means |
|---|---|
| No more "who paid?" | Every cost records who paid and who it was for. |
| Fair to the cent | Equal splits are worked out exactly. Leftover cents never go missing. |
| Fewer payments | What you owe a person is netted against what they owe you. |
| Works for everyone | People without the app still get the weekly SMS and a read-only bill. |
| Nothing gets lost | Unpaid balances carry over to the next week automatically. |
Every expense share, meal order, SMS fee and payment becomes one ledger line: A owes B an amount.
The database function pair_balances() nets those lines for each pair of people, so the app can show
simple instructions such as "Pay Nimal Rs. 450". Every number can be traced back to the entries behind it.
A payment from A to B is stored as B owes A, which cancels A's debt.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Cache Components, server actions), React 19, TypeScript |
| Styling | Tailwind CSS v4 (CSS-first config), Phosphor icons, self-hosted Geist font |
| Data and auth | Supabase: Postgres, Auth, row-level security |
| Hosting | Vercel, with Supabase pg_cron calling the weekly SMS route every hour |
| SMS | Text.lk (Sri Lanka). Notify.lk is also supported. |
git clone https://github.com/kavishkadinajara/kotasa.git
cd kotasa
npm install
cp .env.example .env.local # then fill in the values below
Apply the SQL files in supabase/migrations/ in filename order, either with the Supabase CLI
(supabase db push) or by running them in the SQL editor.
In Supabase, go to Authentication → URL Configuration and set:
<your-app>/auth/callback and http://localhost:3000/auth/callbacknpm run dev
Open http://localhost:3000/setup to create the first account and the first group.
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase publishable key |
SUPABASE_SERVICE_ROLE_KEY | Supabase secret key. Server only, never expose it. |
NEXT_PUBLIC_APP_URL | Public URL of the app, used in bill links and sign-in redirects |
AUTH_EMAIL_DOMAIN | Internal email domain for PIN logins (for example kotasa.local) |
NEXT_PUBLIC_GOOGLE_LOGIN | on shows the Google button, off hides it |
CRON_SECRET | Bearer token pg_cron sends to /api/cron/weekly-sms (also stored in Supabase Vault) |
SMS_PROVIDER | textlk (default) or notifylk |
TEXTLK_API_KEY, TEXTLK_SENDER_ID | Text.lk API token and approved sender ID |
NOTIFY_USER_ID, NOTIFY_API_KEY, NOTIFY_SENDER_ID | Only needed when SMS_PROVIDER=notifylk |
.env.example has a template.
NEXT_PUBLIC_APP_URL to the production URL./api/cron/weekly-sms every hour at :30 UTC (:00 in Sri Lanka). Each group is only
messaged on its own billing day, from its send hour. In the Supabase SQL editor, store the URL and secret once:
select vault.create_secret('https://<app domain>', 'kotasa_app_url'); and
select vault.create_secret('<CRON_SECRET>', 'kotasa_cron_secret');. Without them the job does nothing.https://<project-ref>.supabase.co/auth/v1/callback.NEXT_PUBLIC_GOOGLE_LOGIN=on and redeploy.TEXTLK_API_KEY. Use TEXTLK_SENDER_ID=TextLKDemo until your own sender ID is approved./b/<token>) shows one member's data only, and is excluded from search engines.src/proxy.ts session refresh and login redirect
src/app/
groups/ join/[code]/ your groups, create a group, accept an invite
g/[slug]/ one group: home, expenses, meals, budgets, settle, account, guide, admin
b/[token]/ public read-only bill
api/cron/weekly-sms/ scheduled weekly SMS
actions/ server actions: every write, each with permission checks
src/lib/ auth, ledger, SMS, permissions, group config, dates, money helpers
src/components/ UI components
supabase/migrations/ schema, ledger view, pair_balances(), RLS
npm run dev # start the dev server
npx next typegen && npx tsc --noEmit # type-check
npx eslint src # lint
npm run build # production build
node scripts/make-icons.mjs # regenerate app icons after changing the logo
Built by Vimmik
© 2026 Vimmik. All rights reserved.