JKJWL/Coinvane: Coinvane An Open Sourced Budgeting Web App You Can Host Yourself! - JKJWL/Coinvane

github.com · 2026-08-19 · by Long Nguyen ·github
Coinvane An Open Sourced Budgeting Web App You Can Host Yourself! - JKJWL/Coinvane

JKJWL/Coinvane

Coinvane An Open Sourced Budgeting Web App You Can Host Yourself! - JKJWL/Coinvane

1 stars · 1 forks

README

Coinvane

Self-hosted personal finance · React PWA · Plaid · Google + Microsoft SSO · passwordless email sign-in · zero-knowledge at-rest encryption · Docker Compose deploy Copyright © 2026 Jack Jewell and contributors · Source: https://github.com/JKJWL/Coinvane · License: AGPL v3 (see LICENSE, third-party acknowledgements in NOTICE) · Security policy: SECURITY.md

A self-hosted personal-finance app for one person (or a small household). Bank sync via Plaid, transactions stored encrypted on your own server, mobile PWA you can install on your phone. AGPL, no telemetry, no ads. A note on the license Coinvane is licensed under the GNU Affero General Public License v3.0. That means:

✅ Personal / household use: do whatever you want with it. Run it, modify it, share it with friends. ✅ Forking + modifying: encouraged. Your fork is still AGPL. ⚠ Running it as a paid service for other people (SaaS, multi-tenant hosting, anything where someone pays to access your instance): the AGPL's network-use clause triggers, and you must release your modifications to the source code (including any private patches) under AGPL too. This is by design — the project is for individuals to self-host, not for corporations to repackage and resell.

If AGPL doesn't work for your use case (e.g. you want to fork commercially without sharing your changes), please reach out and we can discuss. A note on security This is a self-hosted app for personal use. You are the operator of your deployment, which means you are responsible for keeping your VPS patched, your SSH hardened, your firewall correct, and your secret keys backed up off-server. The application ships with sensible security defaults (allowlist-only sign-in, strict CSP, AES-256-GCM for tokens and notes, no client-side caching, rate-limiting, prepared statements only, etc.) but those defaults can only protect you if the layer underneath is sound. Read SECURITY.md before you deploy. To report a security vulnerability in the code (as opposed to your specific deployment), please follow the process in SECURITY.md — do not open a public GitHub issue.

Features Accounts & transactions

Bank sync — connect any institution Plaid supports (most US banks, brokerages, credit unions). Polls Plaid on a configurable interval (default every 60 min, editable from the in-app Admin panel without a redeploy), plus webhook-driven near-real-time updates when your bank pushes them. Pending transactions — when your bank reports a charge as pending, it shows up immediately with an amber "Pending" badge so you can tell authorized-but-not-yet-settled spending apart from posted activity. Manual accounts — for banks Plaid doesn't support; balances auto-adjust when you record transactions. Transactions — date-grouped activity feed with filter by account / category, sort options, tap-to-edit. Cash / Credit split — the Transactions tab has a Cash⇄Credit pill at the top. Defaults to Cash on every visit. Credit-card transactions never bleed into your income, cashflow, by-category, or budget totals; they're tallied only by the credit-usage tracker. Per-merchant rules — recategorise a transaction and choose "all future from this merchant"; the rule is saved per-user and applied to every subsequent sync. Manual classification override — flip an already-posted transaction between Income / Expense / Transfer when Plaid gets it wrong, without deleting and re-entering. Split transactions — carve one transaction into multiple category slices (e.g. a Costco run split across Groceries / Household / Fuel). Child rows inherit the merchant + date; the parent becomes a container. Receipt attachments — attach one image (PNG or JPG, ≤5MB) per transaction from the detail sheet, view or reprint later. Uploads are rate-limited (3 per transaction per 5 min, 50 per user per 30 min); a new upload replaces the old file to conserve disk. A pink image marker appears next to any transaction that has a receipt, and the transaction list has a Has receipt sort that groups them at the top. Reconciliation — Quicken-style statement match on any cash or credit account. Enter the statement date + ending balance, tick off transactions until the running difference hits zero, then finalize to lock the pass. Reconciled transactions are frozen with a reconciliation_id so a later pass can't re-tick them. Running balance — when the transaction list is filtered to a single account, each row shows the post-transaction balance underneath the amount. Quicken-parity register view. Check numbers — dedicated Chk# field on manual entry, surfaced next to every row it's set on. Imported QIF N codes populate it automatically. Flag colours + saved views — 7-colour flag palette on any transaction (review, dispute, tax follow-up, whatever) with matching filter chips. Save your current filter/sort/flag/clearing combo as a named view and re-apply it in one click. Void transactions — a state distinct from delete. Voided rows stay visible with a strikethrough but drop out of budgets, cashflow, by-category, net-worth, tax summary, reports, and notifications. Reversible with one click. Payee memorization — on the manual-entry form, tabbing out of the merchant field prefills the category and account based on your most recent matching transaction. Silent if you've already picked something different. Merchant display renames — rename a raw merchant string ("SQ *ACME COFFEE") everywhere it appears without affecting categorization. Merchant rules remain the source of truth for how transactions get categorized. Global keyboard shortcuts (desktop) — n jumps to Transactions and opens the new-txn sheet, / focuses search, [ / ] shift months on the dashboard KPIs. Ignored while typing in a form field. CSV import / export — full transaction roundtrip from the Settings → Data section. CSV columns: date, merchant, category, amount, account, note, pending. On import, accounts are matched by name; unknown names fall back to manual rows. QIF / OFX / QFX / MNY import — migration path for Quicken, Microsoft Money, Mint, or any bank export in one of these formats. Auto-detects the format from the file, binds every imported row to a chosen account, and shifts the manual balance to match. Suspected duplicates against existing rows in the target account (±3 days, same amount) are skipped by default with a prompt to import them anyway. See Microsoft Money import for the native .mny path.

Budgets

Master period — one reset rhythm drives every budget AND the credit-usage tracker. Pick a cadence on the Income card (weekly, bi-weekly, semi-monthly, monthly, yearly, or every N days from a date) and "this week's groceries", "this week's income", and "this week's allocation total" all line up exactly. The "Weekly" option's reset day follows your global Week starts on setting (any day of the week, set in Settings → Appearance). Two budget types — category-based (default) or credit-card-account-based; credit-card transactions are excluded from category budgets to avoid double-counting (swipe + payment). Drag to reorder — touch and mouse both work; order persists across devices. A lock toggle prevents accidental drags on mobile. Edit any budget — amount editable after creation. Category and account are locked once a budget is created (use delete + recreate if you need to change either). Budget history — a date dropdown next to "+ New Budget" walks back through past periods (the last 12 by default). Each period shows what you actually budgeted vs spent AT THAT TIME — amount edits or deletions made later don't rewrite history. Backed by a budget_audit table that snapshots every create / update / delete event. Suggested categories — new-budget form suggests categories you spend on but haven't budgeted yet. Income tracker — pinned at top, no limit; sums positive transactions over the master period. Credit usage tracker — only appears when a credit account is linked; per-card breakdown, also master-period bound. Zero-based-budget summary — three stacked bars at the bottom: current-income allocation, expected-income allocation (when scheduled), and actual budget usage (spent ÷ basis). "X left to budget" indicator; goes rose only when you've over-allocated. Expected income + recurring paychecks — flag any scheduled income transaction as "Budget Expected Income" and it feeds a second bar in the budgets tab. Scheduled income can also loop on a cadence (weekly / bi-weekly / semi-monthly / monthly / yearly / every N days); loops keep the next ~3 months of occurrences populated automatically so cashflow projections stay accurate. The zero-based slider bases itself on expected income when scheduled, otherwise falls back to current income. Transaction type rules — same "apply to all from this merchant" pattern as category rules, but for the income/expense/transfer classification. Fixes merchants Plaid consistently mis-tags (e.g. an ATM cashback that keeps coming back as TRANSFER_OUT). Themed confirmations — destructive actions (delete budget, etc.) prompt with an in-app modal, not the native browser dialog.

Goals & loans

Savings goals with target / progress Contribute button + quick-add chips for deposits or withdrawals (negative amounts clamp at $0) Link to a bank account — when linked, the goal's saved amount is the linked account's live balance, no manual contributions needed (and they're explicitly refused server-side to keep the source of truth single) Loan tracker — a second section under Goals for mortgages, auto loans, student loans, credit-card balances you're paying down. Principal, rate, term, minimum + optional extra payment. Interactive amortization with an extra-payment slider that recomputes payoff date and total interest live. Mortgage escrow breakdown (PITI) — separate monthly amounts for property tax, homeowners insurance, PMI, and other escrow. Loan cards render a proportional stacked bar and full PITI monthly total when any escrow is set. Unified debt simulator — one extra $/mo slider applied across every active loan, with snowball-style cascading of each cleared debt's minimum onto the current target. Toggle Avalanche vs Snowball to see the target flip and the "months / interest saved" headline update live. If any debt's minimum doesn't cover its interest, the simulator surfaces a rose banner instead of running to the 60-year cap. Amortization PDF per loan — every loan card exposes an "Amort PDF" button that downloads a month-by-month schedule with interest / principal / escrow / balance columns. Includes a full-payment summary line (total interest, months to payoff) at the top. Themed delete confirmation instead of the native browser dialog

Bills

Recurring bill templates — set a merchant, expected amount, cadence (weekly / bi-weekly / semi-monthly / monthly / yearly / every N days), and due day. Bills open a new cycle automatically and roll forward. Auto-match on Plaid sync — every incoming transaction is checked against your bill templates by merchant substring + amount band (±40%); a match auto-fills the current cycle as paid without you clicking anything. Manual fallback — mark paid / unpaid / skip on any cycle, edit variance, adjust the expected amount when your electric bill jumps for the summer. Rolling 3-cycle nudge — if your actual paid amount drifts from the template three cycles in a row, the UI suggests updating the template so future forecasts are accurate. Variance tracking — see how far each cycle came in over or under expected. Due-date reminders — every open bill cycle with a due date within your configured N-day window (default 3) fires an in-app notification. Toggle + threshold in Settings → Notifications.

Net worth & cashflow

Net Worth chart with ALL / MTD / YTD / 1M / 3M / 1Y toggle (defaults to ALL — mobile gradient hero + desktop full chart) Spending pulse — compact monthly category breakdown card Cashflow forecast — dashed extension on the monthly cashflow chart projecting the next few months from recurring income + bill templates. Toggle it on/off with the Sparkles button (preference persists across devices); overlay a one-off adjustment (e.g. "expecting a $1,200 refund next month") without creating a real transaction. Cashflow low-balance alert — daily projection over the next 30 days summing scheduled transactions + open bill outflows against your non-credit-account balance. Fires a notification if the projected low point dips below your configured minimum. Configurable in Settings → Notifications. Desktop KPI fullscreen — click any of the three KPI cards (Cashflow / Spending by Category / Net Worth) on desktop to center-fullscreen it. Spending by Category card has its own filters + sort options matching the Net Worth chart.

Investments

Holdings, gains/losses — brokerage syncing via Plaid. Cost-basis handling is Plaid-source-agnostic: NULL basis rows fall back to open-lot basis, and Plaid's inconsistent per-share vs total semantics (Fidelity et al) are normalized at read time so gain/loss doesn't misread by an order of magnitude. Lot tracking + cost basis — each holding is expandable into per-purchase lots (acquired date, quantity, cost-per-share). Sell any lot with a quantity + price; the app records the realized gain, decrements the lot, and flags wash sales when the same security was purchased within ±30 days of the loss. Disallowed loss is proportional to the overlapping share count (sell 100 at a loss, buy back 60 → 60% disallowed, not all of it). Realized + disallowed YTD are exposed on their own KPI card for Schedule D prep. Manual lots roll into the portfolio summary — pure-manual portfolios (no Plaid brokerage) still track total value + gain via the same UI. Fresh-purchase phantom loss fixed — buying at a price the security hasn't yet reported a fresh close for shows "—" instead of a spurious loss equal to the whole basis. Dividend + interest auto-categorization — Plaid's INCOME_DIVIDENDS / INCOME_INTEREST_EARNED categories (plus merchant patterns like dividend, intrst, coupon) are recognized during sync and labelled Interest & Dividends. Coinvane ensures a matching Schedule B category exists on your account so the year-end tax PDF picks it up automatically.

Notifications & per-user settings

Per-type toggles — large transactions, income received ("Congrats You Got Paid!"), approaching budget limit, budget exceeded, goal milestones, bill reminders, cashflow low-balance, overall budget usage %. Each independently on/offable. Configurable thresholds — large-transaction $ amount, income $ amount, budget-warning percentage, bill-reminder days-before, cashflow minimum-balance, budget-usage % are all editable in Settings. Email frequency — instant / daily / weekly (with a weekly send-day picker). Daily and instant are functionally identical until the engine runs more than once a day. Web Push (OS-level notifications) — real lock-screen / notification-tray alerts on desktop, Android, and iOS PWAs. Enable per-device from Settings; per-device revoke via the "Enrolled devices" list. Push is instant-only — inline hooks fire the moment a manual or Plaid transaction lands; a background sweep runs three times a day (ACH windows: 10 AM / 2 PM / 4 PM local) to catch anything the inline path missed. Weighted single-push collapse means multi-alert sweeps produce ONE OS-level banner (the bell still shows every entry), and per-type per-day dedup caps repeat categories. Installed PWAs get an unread-count badge on the home-screen icon via the Web Badging API. Requires VAPID keys in .env — see Web Push setup. Biometric app-lock (mobile only) — require FaceID / TouchID / fingerprint / device passcode to reveal the app on your phone. Doesn't touch your JWT — an expired session still falls back to whichever sign-in methods are configured. Locks on every fresh open + after 5 min of being backgrounded. Disabling the lock or removing an enrolled device requires a fresh biometric verification. See Biometric app-lock for platform notes. Admin broadcast banner — instance-wide message admins can post that shows up as a dismissible yellow / amber / rose slip on every user's desktop app (info / warning / critical severity). Useful for maintenance windows or pushed-update notices. Privacy mode — blurs dollar amounts on the dominant surfaces (hero net worth, KPI cards, account balances, transaction amounts). Hover/focus reveals. Clear all data — nuclear reset in Settings → Danger zone. Wipes every transaction / account / budget / goal / note / attachment / Plaid item / push subscription / biometric credential tied to your login, and revokes every Plaid connection. The users row itself stays so you can start fresh without re-going-through-the-allowlist. Guarded by a typed-email confirmation. Sticky save bar — Settings and the Admin panel share one save UX: a sticky top bar appears only when something is dirty, plus a floating "Save Changes?" ribbon on the right edge once you've scrolled past it.

Admin (Owner / Admin roles)

Owner — the first sign-up. Single per instance. Only role that can edit the Plaid sync interval, edit the email allowlist, promote/demote admins, delete admins, and send sample emails. Admin — can view the admin page and run two destructive actions: removing members and clearing old notifications. Both are audit-logged as "major" events. Members section with per-row role dropdown (Member ⇄ Admin, owner-only). Promotions are staged locally and require Save + a confirmation dialog before they hit the database. Allowlist editor — DB-backed, edits live without restarting the backend. Falls back to the ALLOWED_EMAILS env on a fresh deploy. App info card — Plaid environment, email status, SMTP host, signup mode, row counts. Notification cleanup — bulk-delete in-app notifications older than N days. Audit-logged as a major event. Audit log viewer — last 100 entries with IP + offline GeoIP location. Routine entries auto-prune at 48 h; major entries (role changes, user deletes, bulk wipes, settings edits) survive 7 days and render with a red left border. Per-user test email — owner-only Mail icon next to each Members row sends a sample digest (with a "this is a test" banner) to verify SMTP delivery to that user without logging in as them. Broadcast composer + history — post an instance-wide desktop banner (info / warning / critical) with an optional expiry timestamp; the history list shows past broadcasts + who published each and lets you archive any active one. Rate-limited 10/min so a runaway console can't spam every user. Plaid account-type counts — aggregate view (no user-identifying data) of investment / cash / credit / loan Plaid-linked accounts across every user + total item count. Investment accounts are broken out because they cost more in Plaid product fees, so operators charging a flat member fee to break even can size the number correctly. Manual accounts aren't counted.

Assets & valuables

Non-account holdings — vehicles, boats, jewelry, art, collectibles, property. Track acquired value, current value, and (optionally) a depreciation curve. All roll into net worth alongside your bank accounts and appear in the sidebar under an Assets group. Four value curves — none (you maintain the value manually), straight-line (drops evenly from acquired to salvage over N years), declining-balance (X% of remaining value each year), appreciating (X% growth per year — real estate, art). "Refresh depreciation" snaps the current value to today's projected number in one click, and a nightly worker cron runs the same refresh for every user's non-manual asset so the Net Worth chart drifts on its own without anyone touching it. Damage / repair log — record dents, hail, scratches, or repairs against any asset. Damage rows subtract from current value; repairs add value back. Every event is kept and reversible. The refresh-depreciation button respects the log so a projection re-snap never erases a real-world dent. Loan link — pair a car loan (or any loan-type account) with the asset it backs. The ass

source

github.com · 122 links

Comments (0)

No comments yet