A personal finance tracker built with Next.js and SQLite for managing accounts, transactions, loans, and subscriptions.
- Dashboard — net worth trend over the last 90 days, spend-by-category breakdown for the current month, account balances, and recent transactions at a glance.
- Accounts — create checking, savings, credit card, cash, investment, and loan accounts with an opening balance and currency. Balances are computed as opening balance plus all posted transactions. Accounts can be deleted (with confirmation), which also removes their transactions and investment holdings.
- Transactions — log income and expenses against an account and category, with a note and date. The transactions table supports filtering by type, account, category, and date range, plus pagination, and each row can be deleted individually.
- Transfers — move money between two accounts as a linked pair of transactions, so balances stay consistent on both sides.
- Categories — income and expense categories with a color and icon, seeded with a sensible default set (Salary, Groceries, Rent, Dining Out, etc.), and custom categories can be added or removed.
- Loans — track a loan's principal, interest rate, start date, and term. Logging a payment records it as an expense on the paying account and reduces the remaining balance; the loan auto-closes once fully paid off.
- Subscriptions — track recurring charges on a weekly, monthly, or yearly cycle, log a payment (recorded as a transaction), or cancel a subscription.
- Investments (temporarily disabled) — holdings tracking (units, average cost, current value, gain/loss) per investment account. The code lives in
app/_investmentsand can be re-enabled by renaming it back toapp/investments.
All amounts are displayed in EUR.
- Next.js (App Router) + React + TypeScript
- Tailwind CSS for styling
- Recharts for the dashboard charts
- better-sqlite3 for local, file-based storage
Run the development server:
npm run devOpen http://localhost:3000 to view the app. On first run, a SQLite database is created at data/expense-tracker.db (git-ignored) and seeded with default categories.
To point the app at a different database file (e.g. for testing without touching your real data), set the DB_PATH environment variable:
DB_PATH=/path/to/test.db npm run devnpm run build # production build
npm start # run the production build
npm run lint # lint the codebase