尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Two-person and group expense tracker. Originally a Streamlit app, now a
Next.js 15 app deployable to Vercel with Google sign-in.
The previous Streamlit version is preserved under legacy-streamlit/.
Needs Node 20 or newer and a Postgres you can write to. Never point a local
run at the production database: local runs are allowed to migrate data.
On Windows, copy .env.example .env replaces the first line; the rest is the same
in PowerShell or the Command Prompt.
A free second Supabase project works too: use its pooler URLs as in
.env.example. npm run db:setup-local is safe to re-run.查看完整 README ↗Two-person and group expense tracker. Originally a Streamlit app, now a Next.js 15 app deployable to Vercel with Google sign-in.
The previous Streamlit version is preserved under legacy-streamlit/.
| Layer | Tech |
|---|---|
| Frontend | Next.js 15 (App Router), React 19, Tailwind |
| Auth | Auth.js v5 (next-auth), Google OIDC, JWT sessions |
| Database | Postgres via Prisma 6 (your existing tables) |
| Charts | Recharts |
| Nodemailer (Gmail SMTP) for group invites |
Needs Node 20 or newer and a Postgres you can write to. Never point a local run at the production database: local runs are allowed to migrate data.
cp .env.example .env # then fill in the values (see below)
npm install # also runs `prisma generate`
npm run db:setup-local # creates the tables, the change-log trigger and the PII columns
npm run dev # http://localhost:3000
On Windows, copy .env.example .env replaces the first line; the rest is the same
in PowerShell or the Command Prompt.
The quickest is Docker:
docker run --name ledger-pg -e POSTGRES_PASSWORD=ledger -p 5432:5432 -d postgres:16
Then in .env:
DATABASE_URL="postgresql://postgres:ledger@localhost:5432/postgres"
DIRECT_URL="postgresql://postgres:ledger@localhost:5432/postgres"
A free second Supabase project works too: use its pooler URLs as in
.env.example. npm run db:setup-local is safe to re-run.
See .env.example. Required: DATABASE_URL, DIRECT_URL,
AUTH_SECRET, AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET, PII_SECRET. SMTP vars
are optional (invite emails).
Generate a secret with openssl rand -base64 32, or in PowerShell:
$b = New-Object byte[] 32; [Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($b); [Convert]::ToBase64String($b)
Use a different PII_SECRET locally than in production. The local database
holds only your test data, so it can be anything.
Sign-in is Google only. In Google Cloud Console → Credentials → your OAuth
client, add http://localhost:3000/api/auth/callback/google to the authorized
redirect URIs (the production URI stays). The same client id and secret then
work locally.
How the import works, bank by bank, with every edge case seen so far:
docs/statements/.
/statements reads an HDFC or ICICI credit card PDF on the device, drops the
personal details, and lists EMI, domestic and international rows with GST and
forex markup folded in. The statement's summary (dues, payments, limits, due
date) can be saved under the card, known by its last four digits only, and
every saved statement is listed under Your cards on the same page. It is
on in local development and hidden in production until STATEMENTS_ENABLED=1
is set. To try it, sign in locally and
open Statements in the sidebar (Import in the phone bottom bar).
This app reuses the same Postgres tables the Streamlit app created, so your
existing data works as-is. The Prisma models in
prisma/schema.prisma @map to the real snake_case
columns.
Verify the schema against your live database before first deploy:
npm run db:pull # introspect the live DB and reconcile differences
npx prisma generate
For a brand-new empty database, create the tables with npm run db:push.
Schema changes since the Streamlit era live as SQL files in db/.
Apply them once, in date order, to an existing database (Supabase SQL editor
or psql). 2026_09_group_name_history.sql adds the table that keeps every past
group name with the dates it was in use; 2026_09_app_users_last_name.sql
adds the editable last name and folds old nicknames into the first name;
2026_09_category_dedupe.sql merges categories that differ only by case,
spacing or a plural "s" into one spelling;
2026_09_income_and_unequal_split.sql adds expenses.shares for unequal
group splits, the user_incomes table behind the monthly income and
savings figures, and the app_users columns that drive the income
onboarding step and popup. Deploy the code only after it has run.
2026_09_cards.sql adds the cards and card_statements tables that hold
the statement summaries saved from the statement import.
2026_09_app_users_image.sql adds app_users.image, the Google profile
photo shown in place of member names; run it before deploying that code.
2026_09_expense_payers.sql adds expenses.payers, what each person put in
when several people paid for one expense; run it before deploying that code.
2026_09_expense_statement.sql adds expenses.statement_id, the card
statement an expense was imported from; run it before deploying that code.
2026_10_notification_target.sql adds notifications.target, the expense
or payment a notification is about, so opening it lands on that record;
run it before deploying that code.
2026_10_expense_import_key.sql adds expenses.import_key, a keyed hash of
the statement row an expense was imported from, so a statement read twice
is not added twice; run it before deploying that code.
2026_10_push_subscriptions.sql adds push_subscriptions, the devices that
turned notifications on; run it before deploying that code (until then the
app saves no devices and sends no pushes).
Auth.js uses a different callback path than Streamlit did. In Google Cloud Console → Credentials → your OAuth client, set Authorized redirect URIs to:
http://localhost:3000/api/auth/callback/googlehttps://<your-domain>/api/auth/callback/google(The old Streamlit /oauth2callback URI is no longer used.)
.env.example in the Vercel project
settings. Set AUTH_URL to your production URL.prisma generate && next build.Rotate the Google client secret and
cookie_secret/AUTH_SECRETif they were ever shared in chat or committed.
src/
auth.ts Auth.js (Google, JWT)
app/
login/ Sign-in screen
api/auth/[...nextauth] Auth.js route handlers
(app)/ Authenticated area (sidebar layout)
page.tsx Home + pending invites
add/ log/ summary/ settlement/ groups/ profile/
components/ Sidebar, charts, shared UI
lib/ Prisma client, business logic, server actions
prisma/schema.prisma Mapped to existing Postgres tables
legacy-streamlit/ Previous Streamlit app (reference)