Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A mobile-friendly personal finance diary. Users log what they spend and what they earn each day. The app shows the daily total, analyses each week, month and year, and exports full PDF statements. It works in English and বাংলা, with three themes: light cream (default), dark and a hand-drawn sketchbook theme.
| Area | What it does |
|---|---|
| Accounts | Sign up / log in with a username and password, or Continue with Google (any Gmail account). A one-time recovery code resets a forgotten password without losing data. |
| Daily log | Choose expense or income, write what it was for, then enter the amount and category. The day's total spending is always shown. |
| Past days locked | Adding, editing or deleting entries on a day that has passed needs the password again. Editing then stays unlocked for 5 minutes. |
| Analysis | Week (Saturday to Friday), month and year views with charts, category breakdown, comparison with the previous period, savings rate and insights. |
| Monthly target | Set a spending limit for the month on days 1–3 only (then it locks). Crossing it shows an alert, a system notification and sends an email, once per month. |
| Currency | Bangladeshi Taka (৳) by default. Pick another currency in Settings → Currency: new entries are saved in it and every total, target and report is shown in it. Older entries keep their original amount and are converted at the live rate. The change and its date are written into PDF reports. |
| In Taka | A tab with the live rate of your currency to Taka, a converter, and your day / month / year totals in Taka. Rates come from ExchangeRate-API (free, no key; Google Finance has no public API), with jsDelivr's currency-api as a backup, cached 6 hours in the database. |
| Loans | Log money you borrowed or lent (person, amount, date, optional return date). A loan stays open — on the Daily page and in Loans & Savings — until it is paid back; repayments can be partial, and it closes itself when the full amount is repaid. Overdue loans are flagged. |
| Savings | Put money into or take money out of savings; every change is logged. Shows your balance, how much you saved each of the last 6 months, and whether you are saving this month. You can't take out more than you have. |
| Every account confirms its own email with a 6-digit code (or via Google). Log in with username or email. | |
| Month-end report | When a month ends, its full PDF is emailed automatically (can be switched off). Monthly and yearly PDFs can still be downloaded any time. |
| Monthly and yearly statements with summary, category bars, day-by-day or month-by-month totals and every transaction, in English or Bangla. | |
| Onboarding | A "what is what" slide tour after the first sign-up (swipe on phones). It can be replayed from Settings. |
| Privacy | Users see only their own data. Admins see only counts and anonymous activity signals and can send warnings that the user must acknowledge. |
| Mobile | Responsive layout, bottom navigation on phones, safe-area support and an installable web-app manifest. |
android/ holds the Play Store app. It is a Trusted Web Activity that opens this
same site, so it uses the same database and accounts. GitHub Actions builds the APK and AAB.
See docs/ANDROID.md for building, signing and publishing step by step.npm test includes test/security.test.js, 99 black-box checks against a production-mode server.The parts you already know: HTML, CSS and vanilla JavaScript in the browser, and Node.js on the server. A few small, well-known additions:
| Added | Why |
|---|---|
| Express 5 | The standard, minimal Node web framework for routes and middleware. |
PostgreSQL (pg, hosted on Neon) | The database. Locally, without DATABASE_URL, the same SQL runs on PGlite (Postgres inside Node), so there is nothing to install. |
Node's built-in crypto | scrypt password hashing and AES-256-GCM encryption, with no extra crypto dependencies. |
| Chart.js | Charts on the reports page, served locally rather than from a CDN. |
| google-auth-library | Verifies "Continue with Google" sign-ins on the server (Google's official library). |
| PDFKit | Generates PDFs on the server. The bundled Noto Sans Bengali font renders Bangla correctly. |
| helmet and express-rate-limit | Security headers (a strict CSP) and brute-force protection. |
No frontend framework or build step is involved: edit a file and refresh the page.
SMTP_HOST=smtp.gmail.com, SMTP_PORT=465, SMTP_USER=<that Gmail>, SMTP_PASS=<the app password> and MAIL_FROM=Finance Baba <that Gmail>.Gmail allows about 500 emails a day, plenty for a personal project. Any other SMTP service (Brevo, Zoho, …) works the same way. Until email is set up, sign-up still works and the email step is skipped.
Month-end reports are sent by a daily job: on Vercel by Vercel Cron at 19:15 UTC, which is 1:15 AM in Bangladesh (vercel.json, needs CRON_SECRET), on your own server by a timer inside npm start. Each user's previous month is sent once, according to their own time zone.
Even a full copy of the database is useless to an attacker:
sessions table encrypted with a key derived from the random token in their cookie. The database only stores a hash of that token, so it cannot unlock the key on its own. Sessions end after 30 minutes idle or 12 hours.HttpOnly and SameSite=Strict, with a CSRF header check, a strict Content-Security-Policy and account lockout after 5 wrong passwords.⚠️ Keep
APP_SECRETsafe (ordata/secret.keywhen running locally without it). Without it, nothing in the database can be decrypted. Users who lose both their password and their recovery code cannot get their data back. That is by design.
npm install
cp .env.example .env # optional; a secret is auto-generated if APP_SECRET is empty
npm start # http://localhost:3000
npm run dev # same, but restarts on file changes
Create an admin account, either by setting ADMIN_USERNAME and ADMIN_PASSWORD in .env (created on the next start), or with the command below while the server is stopped (it asks for the password):
npm run create-admin -- admin "Site Admin"
Admins log in on the normal login page and are sent to /admin.
http://localhost:3000 and https://financebaba.vercel.app..env (and in Vercel's environment variables) as GOOGLE_CLIENT_ID=...apps.googleusercontent.com and restart / redeploy.The Google button appears only when GOOGLE_CLIENT_ID is set. First-time Google users still choose a username and password: the password protects past days and works as a fallback login. Existing users can connect or disconnect Google under Settings.
Run the tests:
npm test
To test on your phone, run the server and open http://<your-computer-ip>:3000 on the same Wi-Fi.
server/
config.js Settings and server secret
crypto.js Key derivation, AES-GCM, recovery codes
app.js Express app (shared by local server and Vercel)
index.js Local entry point (`npm start`)
db.js Postgres schema and queries (Neon via pg, or local PGlite)
bootstrap.js Creates the admin from ADMIN_USERNAME/ADMIN_PASSWORD
rateLimitStore.js Rate limits stored in Postgres
users.js Sign-up, login, lockout, password change, recovery, Google linking
google.js Google ID-token verification
sessions.js Database sessions (data key encrypted with the cookie token)
entries.js Encrypted entry storage and validation
dates.js Date helpers in the user's time zone
routes/ auth, entries (+ warnings), reports, admin
reports/ summary (analysis) and pdf (PDFKit statement)
shared/categories.js Categories with English and Bangla labels (browser + server)
shared/currencies.js Supported currencies (browser + server)
public/ index.html (login), app.html (user app), admin.html
css/style.css Light and dark themes, responsive layout
js/ i18n, api, ui helpers, app, reports, onboarding, admin
scripts/create-admin.js
test/api.test.js
The app runs as a Vercel serverless function (api/index.js → server/app.js) and stores everything in Neon Postgres. Pages, CSS and JS are served from Vercel's CDN (public/). Every push to GitHub redeploys automatically.
| Variable (Vercel → Settings → Environment Variables) | Value |
|---|---|
DATABASE_URL | Neon pooled connection string |
APP_SECRET | 64 hex chars, node -e "console.log(require('crypto').randomBytes(32).toString('hex'))". Keep a copy safe: without it the data can never be decrypted. |
NODE_ENV | production |
ADMIN_USERNAME, ADMIN_PASSWORD | optional: creates the first admin on the first request. Remove ADMIN_PASSWORD afterwards. |
GOOGLE_CLIENT_ID | optional: enables Continue with Google |
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, MAIL_FROM | email sending (see Email setup) |
CRON_SECRET | any long random string; protects the daily month-end report job |
Steps:
finance-baba-project (choose the branch under Git settings if it is not main). Framework preset: Other. Build/output settings come from vercel.json.ADMIN_PASSWORD in Vercel and redeploy.Health check: /api/health.
Put the same DATABASE_URL and the same APP_SECRET in your local .env and run npm start. Your PC and the live site then share one database. Leave DATABASE_URL empty to use a private local database instead.
Anything that runs npm start works too (Render, a VPS, Docker via the included Dockerfile): set DATABASE_URL, APP_SECRET, NODE_ENV=production and TRUST_PROXY=1.
APP_SECRET stored separately from those backups.NODE_ENV=production and TRUST_PROXY=1.APP_SECRET from a secrets manager and back it up separately from the database.data/ folder regularly.