尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Split bills. Settle up. Call it quits.
Quits is a free, mobile-first bill-splitting web app for Indian students, built as the course project for Applied Data Science & AI at IISc. It was built with spec-driven development: SPEC.md states what to build, and PLAN.md records how it was built and the evidence for every acceptance criterion.
gemini-3.5-flash-lite).| Part | Choice |
|---|---|
| App | Next.js 16 (App Router, TypeScript), Tailwind CSS 4 with design tokens for both themes, Inter self-hosted via next/font, on Vercel |
| Data | Supabase Postgres. RLS is on for every table with no policies. The database is used only from server code with the secret key, so the browser never talks to Supabase. |
| AI | Gemini structured JSON output (receipts and type-to-add), called only from the server. Receipt images are never stored. |
| Exchange rates | Frankfurter v2 (/v2/rate/{BASE}/{QUOTE}?date=), cached in fx_rates |
| Core logic | Pure, unit-tested modules in lib/: money, splits, simplify, receipt, nlparse, currency, upi, share, csv, recurring, demo-seed, recent-groups, stats, theme, avatar, category-style |
| Writes | Each multi-table write is one Postgres function, so it is atomic. The functions re-check that every id belongs to the group and that payers = splits = total. |
npm install
cp .env.example .env.local # then fill in the values (never commit .env.local)
npm run db:push # applies supabase/migrations to your database
npm run dev # http://localhost:3000
Environment variables (names only):
| Name | Where | Notes |
|---|---|---|
SUPABASE_URL | .env.local, Vercel | |
SUPABASE_SECRET_KEY | .env.local, Vercel | secret |
GEMINI_API_KEY | .env.local, Vercel | secret |
GEMINI_MODEL | .env.local, Vercel | gemini-3.5-flash-lite |
SUPABASE_DB_URL | .env.local only | Session pooler connection string (IPv4), for migrations and DB tests |
SCAN_LIMIT_PER_GROUP, SCAN_LIMIT_PER_APP | optional | daily receipt scans per group (default 30) and AI calls for the whole app (default 300) |
NL_LIMIT_PER_GROUP | optional | daily type-to-add calls per group (default 50) |
APP_URL | GitHub repository variable | used by the daily keep-alive workflow |
Deploy: push to main, and Vercel builds and deploys it. GitHub Actions does two things:
ci.yml runs lint, typecheck and unit tests on every push;keepalive.yml calls /api/health daily so the free Supabase project doesn't pause.npm run lint && npm run typecheck
npm test # unit tests (Vitest): 162 tests
npm run test:db # DB integration tests (24); needs SUPABASE_DB_URL, skipped otherwise
npm run test:db:clean # removes leftover "__test__" groups
npm run build
npm run eval # receipt eval on eval/receipts (see eval/README.md)
npm run eval:nl # type-to-add eval on eval/nl (see eval/nl/README.md)
Both evals call Gemini. Every run is kept, never overwritten, and each run's report says what changed since the previous one and which results are not blind. The results are on the About page.
Receipt eval (eval/REPORT.md): n = 5, small sample (one receipt moves a per-receipt rate by 20 points). Five real receipts with ground truth checked by hand against the paper bills. The main result is run 3:
| Overall | When answered | |
|---|---|---|
| Answer rate (read within 25 s) | 80% (4 of 5) | — |
| Item F1 | 45.2% | 100% |
| Total accuracy | 80% | 100% |
| Reconciliation (items + tax + charges = total ± ₹1) | 80% | 100% |
Run 3 is not blind for r01 and r04: run 2 revealed two prompt gaps there, which were fixed. The low overall F1 comes from one receipt that timed out (all 34 of its items count as missed), not from misreads.
Type-to-add eval (eval/nl/REPORT.md): n = 30, small sample. Twenty sentences were written by Claude and ten by the human, all reviewed by the human; seven are deliberately ambiguous. The main result is run 3:
| Overall | When answered | |
|---|---|---|
| Answer rate (within 20 s) | 80% (24 of 30) | — |
| Amount | 76.7% | 95.8% |
| Exact match | 76.7% | 95.8% |
The 6 unanswered sentences were Gemini "high demand" errors (HTTP 503) or timeouts, not wrong answers.
The eval/synthetic/ run only smoke-tests the script.
Tested on a Samsung phone against the deployed app, 2026-10-16:
| Path | GPay | PhonePe | Paytm |
|---|---|---|---|
upi://pay link from a website ("Pay via UPI app") | blocked: misleading "exceeded bank limit" error at ₹1 | blocked | blocked |
| QR shown on a laptop, scanned by the phone | works: payee and ₹1.00 filled in | — | — |
| QR screenshot scanned from the gallery | works | — | — |
As a result, settle-up is QR-first (SPEC v0.5, D-18). The link is kept only as a best-effort option, labelled "May be blocked by some UPI apps". The 2026-10-19 production check confirmed the QR also scans in the dark theme: on screen, full screen and from the saved image.
58 of 60 acceptance criteria pass, all with evidence in PLAN.md → "AC status": unit and DB tests, headless-browser checks, and live checks on production and on an Android phone. The two failures are Should-level accuracy targets:
| AC | Target | Result (n is small) | Why |
|---|---|---|---|
| AC-25 (Should) | receipt item F1 ≥ 0.80 and reconciliation ≥ 0.70 | F1 0.452, reconciliation 0.80 (run 3, n = 5) | One receipt timed out at 25 s, so all 34 of its items count as missed. When answered: F1 1.00, reconciliation 1.00. |
| AC-52 (Should) | type-to-add amount ≥ 95% and exact match ≥ 80% | 76.7% and 76.7% (run 3, n = 30) | Six sentences got no answer (Gemini 503 or timeouts). When answered: amount and exact match 95.8%. |
Both are reported as measured. Fixes driven by the evals are labelled in the reports, and the next run is marked not blind:
Nothing was tuned just to raise a score.
| File | What it is |
|---|---|
| SPEC.md | The specification, v1.7: goals and users, constraints, data model and interfaces, 73 requirements in EARS form (49 Must, 24 Should), 60 pass/fail acceptance criteria, deliverables, non-goals, risks, decisions D-1 to D-41, and a changelog from v0.1 to v1.7. When the code and the spec disagreed, the spec was changed first and logged. |
| PLAN.md | The build plan: phases 1–12 with tasks mapped to requirements and ACs (AUTO / HUMAN), the build log, SPEC change proposals, and the AC status table, with evidence for every criterion. |
| eval/README.md, eval/nl/README.md | How the two evaluations work, their ground-truth rules, and every kept run (REPORT*.md, results*.json). |
AGENTS.md, .claude/settings.json | Instructions and settings for the coding agent (Claude Code). |