yabasha/fintrack
FinTrack is a single-user personal finance command center designed for developers who juggle multiple income streams and multi-currency transactions. It provides a robust, local-first alternative to bloated accounting software, offering a comprehensive suite of tools for tracking expenses, managing budgets, and invoicing freelance clients. It is built for power users who prioritize data ownership and want a streamlined, high-speed interface for their financial life.
The project employs a modern, decoupled architecture utilizing a Laravel 13 backend and a Next.js 16 frontend. The stack leverages MySQL 8.4 for persistence, Redis for caching, and Meilisearch for high-performance full-text search. On the frontend, it uses React 19 with the App Router, TanStack Query for state management, and Tailwind CSS with shadcn/ui for a clean, dark-mode-first aesthetic. Development is optimized with Bun for fast package management and Docker for reproducible, self-hosted deployment.
What makes this project notable is its strict adherence to local-first principles. By keeping all financial data within a self-hosted environment and avoiding third-party cloud dependencies, it ensures privacy and speed. The codebase is well-structured, featuring thoughtful integrations like URL-synced state, background jobs for recurring transactions, and robust automated testing, making it a great reference for anyone looking to build a sophisticated, production-ready SPA.
- Stars
- 1
- Forks
- 0
- Language
- TypeScript
- Updated
- 6h ago
§ Readme
Edit on GitHub ↗FinTrack
Personal finance command center — built by a developer, for a developer.
What It Does
Single-user finance dashboard for tracking income, expenses, budgets, exchange rates, and freelance invoices. Designed for someone with multiple income streams, multi-currency transactions, and zero patience for bloated accounting software.
Features
- Quick transaction entry — amount, category, done in seconds
- Multi-currency support — JOD base with 165+ currencies, live exchange rates
- Dashboard — balance overview, cashflow charts, budget progress, spending breakdown
- Transaction management — full CRUD, advanced filters, bulk actions, URL-synced state
- Exchange rates — live rates table, historical charts, currency converter
- Budgets — category-based spending limits with progress tracking
- Analytics — spending trends, freelance income tracking, net worth over time
- Invoicing — create, send, and track freelance invoices
- Recurring transactions & bill payments — scheduled jobs auto-generate them
- Settings — categories, accounts, security, data import/export, appearance
Tech Stack
Backend
- Laravel 13 — PHP 8.3+, Sanctum auth (cookie-based SPA)
- MySQL 8.4 — primary database
- Redis 7 — sessions, cache, queue
- Meilisearch — full-text search
Frontend
- Next.js 16 — React 19, Turbopack, App Router
- Bun 1.3.14 — package manager + runtime
- Tailwind CSS 4.2 — OKLch color palette, dark mode first
- shadcn/ui (base-ui) — component library
- TanStack Query — data fetching + cache
- React Hook Form + Zod — form handling + validation
- Recharts — charts and data visualization
Getting Started
Prerequisites
- Docker Desktop (or Docker Engine + Compose)
Quick Start (Docker)
cp .env.example .env
make setup
That's it. Builds containers, generates app key, runs migrations + seeds.
Services:
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| MySQL | localhost:3307 |
| Redis | localhost:6380 |
| Meilisearch | http://localhost:7700 |
Host ports for MySQL (3307) and Redis (6380) are offset from the defaults so they don't collide with Herd or other local services. Override via
FORWARD_DB_PORT/FORWARD_REDIS_PORTin.env. All forwarded ports are bound to127.0.0.1.
Default Login
After make setup runs the seeders, sign in with:
| Field | Value |
|---|---|
admin@fintrack.local | |
| Password | changeme123 |
Change the password from Settings → Security immediately after first login.
Seed the Database
make setup seeds automatically. To re-seed (or seed an existing database) without rebuilding everything:
make seed # Run all seeders
make fresh # Drop, re-migrate, re-seed (destroys data)
make shell # Shell into the backend container
php artisan db:seed --class=CategorySeeder # Run a single seeder
php artisan db:seed --class=SampleTransactionSeeder
Seeders live in backend/database/seeders: UserSeeder (default login), CurrencySeeder, CategorySeeder, AccountSeeder, PaymentMethodSeeder, TagSeeder, SettingsSeeder, ExchangeRateSeeder, ClientSeeder, InvoiceSeeder, BudgetSeeder, SavingsGoalSeeder, BillSeeder, SampleTransactionSeeder.
Useful Commands
make up # Start all containers
make down # Stop all containers
make rebuild # Rebuild + restart
make logs # Tail all logs
make shell # Shell into backend
make migrate # Run migrations
make fresh # Drop, re-migrate, re-seed
make test # Run tests
make help # List all commands
Frontend Dev (without Docker)
cd frontend
bun install
bun run dev
Project Structure
fintrack/
├── docker-compose.yml # Full stack orchestration (5 services)
├── Makefile # Dev commands
├── backend/ # Laravel 13 API
│ ├── app/
│ │ ├── Enums/ # PHP enums (TransactionType, Currency, etc.)
│ │ ├── Http/
│ │ │ ├── Controllers/ # REST API controllers
│ │ │ ├── Middleware/ # CSP, ForceHTTPS, EnsureSessionValid
│ │ │ ├── Requests/ # Form request validation
│ │ │ └── Resources/ # API response transformers
│ │ ├── Models/ # Eloquent models
│ │ ├── Services/ # ExchangeRate, CurrencyConversion, Analytics
│ │ └── Jobs/ # Background jobs (rates, recurring, bills)
│ ├── database/
│ │ ├── migrations/
│ │ └── seeders/ # Categories, currencies, demo data
│ └── routes/api.php
├── frontend/ # Next.js 16 SPA
│ └── src/
│ ├── app/ # App Router pages (auth + dashboard groups)
│ ├── components/ # UI components (shadcn/ui base-ui)
│ ├── lib/
│ │ ├── api.ts # Sanctum SPA client (CSRF, 401/419 handling)
│ │ ├── hooks/ # TanStack Query hooks
│ │ └── utils.ts
│ └── types/ # TypeScript models (source of truth)
├── PLAN.md # Full feature spec and roadmap
└── README.md
Environment
| Variable | Default | Description |
|---|---|---|
BACKEND_PORT | 8000 | Backend API host port |
FRONTEND_PORT | 3000 | Frontend dev server host port |
FORWARD_DB_PORT | 3307 | MySQL host port (offset from 3306 to avoid Herd) |
FORWARD_REDIS_PORT | 6380 | Redis host port (offset from 6379 to avoid Herd) |
FORWARD_MEILISEARCH_PORT | 7700 | Meilisearch host port |
DB_DATABASE | fintrack | MySQL database name |
DB_USERNAME | fintrack | MySQL user |
DB_PASSWORD | secret | MySQL password |
NEXT_PUBLIC_API_URL | http://localhost:8000 | Backend URL for the frontend |
SANCTUM_STATEFUL_DOMAINS | localhost:3000,localhost | Sanctum SPA domains |
Security Notes
- Single-user auth — no public registration
- Session bound to IP + User-Agent (
EnsureSessionValidmiddleware) - Auto-logout after 15 min of inactivity
- All monetary data stays local; only exchange-rate fetches reach out
- Receipts encrypted on the local disk
Author
Built by Bashar Ayyash.
License
Released under the MIT License.
§ Cite this project
For papers, blog posts, & AI referencesBashar Ayyash. (2026). yabasha/fintrack [Computer software]. https://yabasha.dev/open-source/fintrack§ Related repositories
yabasha/monolith
This project provides a robust, scalable architecture for modern full-stack development by combining a Laravel 12 backend with a Next.js 16 frontend in a unified monorepo. It is designed for developers who value explicit structure, clear boundaries between application layers, and high-performance workflows. By organizing the core application code within an apps directory and isolating shared UI primitives in a packages workspace, it enables teams to build complex systems while maintaining a consistent design language.
- TypeScript
- 2 stars
- 0 forks
- updated 4mo ago
yabasha/composable-ai-stack
The Composable AI Stack (CAS) is a production-ready monorepo template designed for developers building AI-integrated SaaS applications. It provides a structured, modular foundation that abstracts the complexity of scaling from localized prototyping to robust enterprise deployments. By standardizing the integration of LLMs, database interactions, and billing logic, it enables teams to focus on core product features rather than boilerplate architecture.
- TypeScript
- 1 stars
- 0 forks
- updated 3d ago
yabasha/yabasha-gex
GEX is a versatile command-line interface tool designed to help developers audit, document, and manage their Node.js package environments. It provides a structured approach to generating reproducible reports for local projects and globally installed packages. By supporting multiple runtime environments—Node.js (npm), Bun, Yarn, and pnpm—it serves as a unified utility for teams needing to track dependency states, enforce license compliance, or simplify vulnerability auditing across diverse infrastructure.
- TypeScript
- 1 stars
- 0 forks
- updated 3d ago