A full-stack personal finance tracker with multi-locale support, built as a progressive enhancement of a course project into a production-grade application.
(https://rhinocan.github.io/docs/MoneyTracker.png)
MoneyTracker lets users record income and expense transactions, view a live account summary, and manage their data — all behind a secure authenticated session. The project began as a follow-along with a Brad Traversy course and was subsequently rebuilt from the ground up with a production mindset: TypeScript throughout, a Vuetify component library, Pinia state management, Supabase for auth and persistence, full i18n support across 16 locales, and a comprehensive automated test suite.
The goal was not just a working app but a demonstrably well-engineered one — the kind where the code is as considered as the features.
- Authentication — register, log in, and log out via Supabase Auth; each user's data is fully isolated
- Transaction management — add, edit, and delete income and expense transactions with date tracking
- Account summary — live-calculated total income, total expenses, and net balance
- Multi-locale support — 16 locales with locale-aware currency formatting, decimal separators, and date display; includes RTL support for Arabic (ar-SA)
- Data management — export transactions to CSV, restore settings to defaults, or wipe all data
- Keyboard shortcuts — power-user shortcuts for form submission and navigation
- Persistent settings — locale and display preferences saved per user to Supabase
- Responsive layout — works on desktop and mobile
| Layer | Technology |
|---|---|
| Framework | Vue 3 (Composition API) |
| UI Library | Vuetify 3 |
| State Management | Pinia |
| Language | TypeScript |
| Backend / Auth / DB | Supabase (PostgreSQL + Row Level Security) |
| Internationalisation | vue-i18n (16 locales) |
| Routing | Vue Router 4 |
| Build Tool | Vite |
| Unit Testing | Vitest |
| E2E Testing | Playwright |
| Error Logging | Sentry |
| Analytics | PostHog |
| Deployment | GitHub Pages via deploy script |
- Node.js 18+
- A Supabase project with the transactions and settings tables provisioned
# 1. Clone the repository
git clone https://github.com/rhinocan/MoneyTracker.git
cd MoneyTracker
# 2. Install dependencies
npm install
# 3. Configure environment variables
cp .env.example .env
# Edit .env and fill in your Supabase URL and anon key
# 4. Start the development server
npm run devThe app will be available at http://localhost:5173/MoneyTracker/.
| Variable | Description |
|---|---|
VITE_SUPABASE_URL |
Your Supabase project URL |
VITE_SUPABASE_ANON_KEY |
Your Supabase anonymous (public) key |
# Run all unit tests
npm run test
# Run with coverage report
npm run test:coverageCurrent coverage: 99.28% statement, 93.93% branch across 614 tests in 33 files.
# Run all E2E tests (Chromium)
npx playwright test --project=chromium
# Run a single spec file
npx playwright test --project=chromium tests/e2e/transactions.spec.ts
[Exception: forgotPassword and auth have their own separate projects so they are invoked via:
npx playwright test --project=forgotPassword-tests
npx playwright test --project=auth-tests]
# View the HTML report from the last run
npx playwright show-reportE2E tests require the dev server to be running and a valid test account (rhinocan@outlook.com / rschl0chA) to exist in your Supabase project.
Current E2E status: 60/63 passing (3 skipped)* across 6 spec files (accessibility, auth, dataManagement, forgotPassword, locales, transactions).
BASE_URL=https://rhinocan.github.io/MoneyTracker npx playwright test --project=chromiumThe app is deployed to GitHub Pages from the gh-pages branch.
# From the main branch
./deploy.shThe script builds the app and pushes the dist/ folder to gh-pages. Build and deploy status is visible in the repository's Actions tab. Occasional GitHub 500/502 errors during deploy are transient — re-running the script resolves them.
This project started as a follow-along with a Brad Traversy course and was incrementally upgraded into its current form. Notable additions beyond the original course material:
- Replaced
localStoragewith Supabase for persistent, per-user data - Replaced plain JavaScript with TypeScript throughout
- Replaced Vue components with Vuetify 3
- Replaced prop drilling with Pinia stores
- Added Vue Router with authenticated route guards
- Added vue-i18n with 17 locales and RTL support
- Added a full unit test suite (Vitest) with >99% statement coverage
- Added a full E2E test suite (Playwright) with 60 passing tests
- Added Sentry for error logging and PostHog for analytics
- Added CSV export and a data management screen
- Add Playwright auth state caching to speed up the E2E suite
- No category tagging — transactions cannot be filtered or grouped by category
- No recurring transactions — each transaction must be entered manually
- Category tagging and filtering for transactions
- Charts and spending trend visualisation
- Recurring transaction support
- Dark mode
- Tax-inclusive vs. tax-exclusive amounts — in countries like Canada where sales tax (GST/HST/PST) is added at the till rather than included in the sticker price, it would be useful to record both the pre-tax amount and the tax paid separately, giving a clearer picture of actual spending
- Additional locales and currencies as demand warrants
Built with significant assistance from Claude (Anthropic), ChatGPT (OpenAI), and Gemini (Google) — each contributed at various points throughout development, particularly Claude. Thanks also to Brad Traversy for the original course project that served as the starting point.