A full-stack personal finance tracker with multi-currency support, investment portfolio monitoring, recurring transactions automation, and real-time market data integration.
- Overview
- What's New
- Screenshots
- Quick Start
- Architecture
- Core Features
- How It Works
- Security
- Development
- API Documentation
Finance Manager is a modern, privacy-focused personal finance application that helps you track your net worth, manage multiple accounts, monitor investments, automate recurring transactions, and analyze spending patterns. Built on Cloudflare's edge network for global performance and security.
Security & Reliability
- Zod input validation β All mutation endpoints (POST/PUT) are validated via Zod schemas before reaching business logic. Invalid payloads return structured
400errors with per-field details. - Structured error codes β
AppErrorclass with typedErrorCodeconstants. Every error returns{error, code}JSON β no more untyped string messages. - Rate limiting β Sliding window per-IP rate limiter (default: 300 req/60 s). Returns
429withRATE_LIMITEDcode when exceeded. - CSP & security headers β
Content-Security-Policy,X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy, andPermissions-Policynow set on all Cloudflare Pages responses. - Audit log β Every create/update/delete on accounts and transactions is recorded in the
audit_logD1 table with action, entity type, entity ID, and timestamp. - Structured JSON logging β All
console.logcalls replaced with a typedloggerutility outputting{level, message, timestamp, ...context}JSON for easy log querying.
Performance
- DB indexes β 8 new indexes on hot query columns (
account_id,date,category_id,linked_transaction_id) acrosstransactions,investment_transactions, andrecurring_schedules. - Type safety β Removed all
any[]types from repositories. All D1 query parameters are now typed as(string | number | null)[].
UI/UX
- Transaction search β Search bar in the transaction list filters by description, category name, and account name in real time.
- Skeleton loaders β Replaced static loading states with per-row animated skeletons and staggered delays for a polished loading experience.
- Mobile bottom navigation β Fixed bottom nav bar on screens smaller than
lg. Desktop retains the sidebar layout.
Code Quality
useFinanceDatahook β All data fetching, state, and callbacks extracted fromApp.tsxinto a dedicated hook.App.tsxreduced from ~760 to ~280 lines.- Vitest test suites β Unit tests for all Zod validators,
AppError/ErrorCode, and theuseFinanceDatahook.
cd api
npx wrangler d1 execute finance-db --remote --file=schema.sql
npm run deploycd client
npm run build
npx wrangler pages deploy dist --project-name=finance-clientUse the deployment script to deploy everything at once:
./deploy.sh finance-clientThis script handles:
- Database schema updates β Applies migrations to your D1 database
- API deployment β Deploys backend to Cloudflare Workers
- Client build & deploy β Builds React app and deploys to Cloudflare Pages
Finance Manager follows clean architecture principles with clear separation of concerns:
- Backend: Layered architecture with controllers, services, repositories, DTOs, and mappers
- Frontend: Component-based React architecture with context for global state
- Database: Edge-deployed SQLite (Cloudflare D1) for low-latency data access
- Deployment: Fully automated via deployment script
For detailed architecture documentation, see API/ARCHITECTURE.md.
Backend
- Runtime: Cloudflare Workers (serverless, edge-deployed)
- Framework: Hono ^4.0 (lightweight web framework)
- Database: Cloudflare D1 (SQLite at the edge)
- Market Data: Yahoo Finance API (yahoo-finance2 ^3.10)
- Architecture: Clean architecture with controllers, services, repositories, DTOs, and mappers
Frontend
- Framework: React ^19.2 with TypeScript
- Build Tool: Vite ^7.2
- Styling: Tailwind CSS ^4.1 with custom design system
- Charts: Recharts ^3.5 for data visualization
- Icons: Lucide React ^0.554
- State: React Context API (Privacy, Alerts, Locked Accounts)
- PWA: Progressive Web App with offline support and service workers
- Date Handling: date-fns ^2.30 for date formatting and manipulation
- UI Utilities: clsx ^2.1, tailwind-merge ^3.4
finance/
βββ api/ # Backend (Cloudflare Workers)
β βββ src/
β β βββ config/ # Application configuration
β β βββ controllers/ # HTTP request handlers
β β βββ dtos/ # Data Transfer Objects
β β βββ errors/ # AppError class + ErrorCode constants
β β βββ mappers/ # Entity-DTO mapping
β β βββ middlewares/ # auth, CORS, rate limiting, validation
β β βββ models/ # Domain entities + AuditLog
β β βββ repositories/ # Database access layer (typed D1Value[])
β β βββ services/ # Business logic layer
β β βββ tests/ # Vitest unit tests
β β βββ types/ # TypeScript types
β β βββ utils/ # logger + helpers
β β βββ validators/ # Zod schemas for all mutation endpoints
β β βββ index.ts # Application entry point
β βββ migrations/ # D1 SQL migrations (001β004)
β βββ wrangler.toml # Cloudflare Workers config
β βββ package.json
β
βββ client/ # Frontend (React + Vite)
β βββ src/
β β βββ components/ # Feature module components
β β βββ context/ # React context providers
β β βββ hooks/ # useFinanceData + other hooks
β β βββ lib/ # Utility functions
β β βββ test/ # Vitest tests + setup
β β βββ App.tsx # Root layout + navigation
β β βββ config.ts # API base URL + apiFetch
β β βββ main.tsx # Entry point
β βββ public/
β β βββ _headers # Cloudflare Pages security headers (CSP etc.)
β β βββ ... # PWA icons, favicon
β βββ vite.config.ts # Vite + Vitest + PWA configuration
β βββ package.json
β
βββ AGENT.md # Developer guide for Claude/AI sessions
βββ deploy.sh # Automated deployment script
βββ package.json # Workspace root
β¨ Multi-Account Management
- Cash accounts (checking, savings, wallet)
- Investment accounts (stocks, crypto, manual assets)
- Multi-currency support with real-time conversion
- Account locking (prevent accidental modifications)
- Account exclusion options (exclude from net worth or cash balance calculations)
π Transaction Tracking
- Categorized income & expenses
- Recurring transactions with automated scheduling
- Linked transfers between accounts
- Custom categories with emoji icons
- Split transactions - divide a single transaction across multiple categories
- Balance adjustments - reconcile account balances with single or split transactions
- Transaction filtering by type, category, and date range
- Monthly transaction views with pagination
π Investment Portfolio
- Real-time stock/crypto prices via Yahoo Finance
- Portfolio value tracking with multi-currency support
- Transaction history (buy/sell)
- Performance charts and analytics
- Auto-refresh prices (every 5 minutes)
- Manual asset tracking without market data
π Privacy & Security
- Privacy mode to hide sensitive financial data
- Persistent user preference (localStorage + cookie)
- Quick eye icon toggle in header
- Account locking to prevent accidental changes
- Alert system for user notifications
- Three-layer security model (Cloudflare Access, API Key, CORS)
π Analytics Dashboard
- Net worth overview with real-time calculation
- Income vs. expenses tracking
- Category breakdown charts
- Monthly trends and patterns
- Date range filtering for custom periods
- Period selection (7 days, 30 days, 90 days, year, all time, custom)
- Cash flow visualization
π Recurring Transactions
- Automated recurring transaction management
- Daily, weekly, and monthly schedules
- Projected cash flow (end of month)
- Next 30 days income/expense forecasting
- Account status monitoring (sufficient funds alerts)
- Interactive calendar view of upcoming transactions
- Cloudflare Cron Triggers for automated processing
βοΈ Settings & Customization
- Master currency selection (HUF, EUR, USD, GBP, CHF, PLN, CZK, RON)
- Category management with custom icons (150+ emoji options)
- Privacy mode toggle
- Cache management and force reload
- Data export (CSV and JSON formats)
- PWA cache control
π Global Deployment
- Edge-deployed on Cloudflare network
- Sub-50ms response times worldwide
- Automatic HTTPS and DDoS protection
π± Progressive Web App (PWA)
- Install on mobile devices and desktop
- Offline support with service workers
- Auto-updates and caching
- Native app-like experience
- Custom app icons and splash screens
The application supports two types of accounts:
-
Cash Accounts β Traditional bank accounts, wallets
- Direct balance management
- Currency-specific
-
Investment Accounts β Asset holdings
- Stock/Crypto: Auto-updates price from Yahoo Finance
- Manual: User-defined assets without market data
- Balance calculated from:
transactions Γ current_price
Every financial action is recorded as a transaction:
User Action β Transaction Record β Account Balance Update
Example: Transfer $100 from Checking to Savings
- Creates 2 linked transactions:
- Transaction A: Checking -$100 (expense)
- Transaction B: Savings +$100 (income)
- Both transactions share a
linked_transaction_id - Account balances update atomically
Investment Transactions are tracked via regular transactions with a price field:
- Buy: Negative amount, increases holdings
- Sell: Positive amount, decreases holdings
Investment accounts use a transaction-based approach:
- User buys 10 shares of AAPL at $150/share
- System creates transaction:
-$1500amount,price: 150,quantity: 10 - Current balance =
SUM(transactions.amount / price) Γ current_market_price
Auto-refresh runs on:
- Page load
- Manual refresh button
- Every 5 minutes (in dashboard view)
Privacy mode uses React Context to globally mask sensitive data:
// When enabled, transforms:
"$12,345.67" β "β’β’β’β’β’β’"
"150 shares" β "β’β’β’"- Preference saved in localStorage + cookie
- Survives page refresh
- Applies to: balances, amounts, quantities, charts
- Configurable startup behavior (hide on startup option)
- Quick toggle via eye icon in header
The application supports automated recurring transactions with advanced scheduling:
- Mark any transaction as recurring when creating it
- Choose frequency: daily, weekly, or monthly
- Set specific days (day of week for weekly, day of month for monthly)
- A Cloudflare Cron Trigger runs daily at midnight
- Recurring schedules are automatically processed and transactions created
- Configured in
wrangler.toml:crons = ["0 0 * * *"]
Features:
- Projected cash flow calculations (end of month)
- Next 30 days income/expense forecasting
- Account status monitoring with insufficient funds alerts
- Interactive calendar view showing upcoming transactions
- Support for both single transactions and transfers
This enables automated handling of:
- Regular salary deposits
- Monthly subscriptions
- Recurring bills and expenses
- Weekly allowances
- Daily automated transactions
Split a single transaction across multiple categories for detailed expense tracking:
- Choose to split when adjusting an account balance or creating a transaction
- Define multiple splits with individual amounts, descriptions, and categories
- System ensures total matches the transaction amount
- Visual indicators show split vs. allocation progress
- Percentage-based splitting for easy distribution
Use cases:
- Shopping trips with groceries, household items, and personal care
- Utility bills split between housing and utilities categories
- Mixed business/personal expenses
- Detailed expense tracking for reimbursements
Reconcile account balances when they don't match reality:
- Enter the correct balance in account settings
- System calculates the adjustment amount
- Choose between:
- Single transaction: One adjustment entry in a category
- Split transaction: Distribute adjustment across multiple categories
- Account balance updates to match the correct amount
Perfect for:
- Fixing data entry errors
- Reconciling with bank statements
- Adjusting for cash transactions not yet recorded
- Correcting rounding differences in currency conversions
Three-Layer Security Model:
-
Cloudflare Access (Frontend)
- Email-based authentication
- Only authorized users can view the app
- 24-hour session duration
-
API Key Authentication (Backend)
- Every API request requires
X-API-Keyheader - Key stored in environment variables
- Validates on every request
- Every API request requires
-
CORS Protection (Backend)
- Origin whitelist validation
- Rejects unauthorized domains
- Configurable via
ALLOWED_ORIGINSenv var
-
Zod Input Validation
- All POST/PUT payloads validated before reaching business logic
- Returns
400 {error, code: "VALIDATION_ERROR", details: [{field, message}]}on failure
-
Rate Limiting
- Sliding window per-IP (default: 300 req/60 s)
- Returns
429 {error, code: "RATE_LIMITED"}when exceeded
-
Security Headers (Cloudflare Pages
_headers)Content-Security-Policyrestricting scripts and connections to known originsX-Frame-Options: DENY(clickjacking protection)X-Content-Type-Options: nosniff(MIME sniffing protection)Referrer-Policy: strict-origin-when-cross-originPermissions-Policydisabling camera, microphone, geolocation
-
Audit Log
- Every create/update/delete on accounts and transactions written to
audit_logD1 table
- Every create/update/delete on accounts and transactions written to
Environment Secrets:
API_SECRETβ Backend API keyALLOWED_ORIGINSβ Comma-separated allowed domainsVITE_API_KEYβ Client-side API key (injected at build time)
- Node.js 18+ and npm
- Cloudflare account with Workers + D1 access
- Wrangler CLI (installed via npm)
-
Clone and install dependencies:
git clone <repo-url> cd finance npm install
-
Configure the API:
cd api cp wrangler.toml.example wrangler.toml # Edit wrangler.toml: # - Set database_id (create D1 database first) # Create .dev.vars for local development secrets: echo "API_SECRET=your-secret-key" > .dev.vars echo "ALLOWED_ORIGINS=http://localhost:5173" >> .dev.vars
-
Initialize database:
npx wrangler d1 execute finance-db --local --file=schema.sql
-
Configure the client:
cd ../client # Create .env.local file: echo "VITE_API_KEY=your-api-key-here" > .env.local echo "VITE_API_DOMAIN=localhost:8787" >> .env.local
-
Run development servers:
cd .. npm run dev # API: http://localhost:8787 # Client: http://localhost:5173
# API unit tests (validators + error codes)
cd api && npm test
# Client unit tests (hooks + components)
cd client && npm test
# Watch mode
cd api && npm run test:watch
cd client && npm run test:watchAPI Secrets:
For local development, create .dev.vars file (not committed to git):
API_SECRET=your-secret-key
ALLOWED_ORIGINS=http://localhost:5173For production, use Wrangler CLI to set secrets:
wrangler secret put API_SECRET
wrangler secret put ALLOWED_ORIGINSClient Environment Variables:
For local development, create .env.local file:
VITE_API_KEY=your-secret-key
VITE_API_DOMAIN=localhost:8787For production build, create .env.production.local or set during build:
VITE_API_KEY=your-production-key
VITE_API_DOMAIN=finance-api.yourdomain.workers.devImportant: Client environment variables are baked into the JavaScript bundle at build time. The .env files are never deployed - only the built artifacts.
Base URL: https://api.finance.yourdomain.com
Authentication: Include X-API-Key header in all requests.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Health check |
GET |
/version |
API version |
| Accounts | ||
GET |
/accounts |
List all accounts |
POST |
/accounts |
Create account |
PUT |
/accounts/:id |
Update account |
DELETE |
/accounts/:id |
Delete account |
| Transactions | ||
GET |
/transactions |
List all transactions |
GET |
/transactions/paginated |
Get paginated transactions |
GET |
/transactions/date-range |
Get transactions by date range |
GET |
/transactions/from-date |
Get transactions from a specific date |
POST |
/transactions |
Create transaction |
PUT |
/transactions/:id |
Update transaction |
DELETE |
/transactions/:id |
Delete transaction |
| Categories | ||
GET |
/categories |
List categories |
POST |
/categories |
Create category |
PUT |
/categories/:id |
Update category |
DELETE |
/categories/:id |
Delete category |
POST |
/categories/reset |
Reset categories to defaults |
| Investment Transactions | ||
GET |
/investment-transactions |
List investment transactions |
POST |
/investment-transactions |
Create investment transaction |
DELETE |
/investment-transactions/:id |
Delete investment transaction |
| Recurring Schedules | ||
GET |
/recurring-schedules |
List all recurring schedules |
POST |
/recurring-schedules |
Create recurring schedule |
PUT |
/recurring-schedules/:id |
Update recurring schedule |
DELETE |
/recurring-schedules/:id |
Delete recurring schedule |
POST |
/recurring-schedules/process |
Process recurring schedules (cron) |
GET |
/recurring-schedules/calendar |
Get calendar view of upcoming transactions |
| Transfers | ||
GET |
/transfers/exchange-rate |
Get exchange rate between currencies |
POST |
/transfers |
Create transfer between accounts |
| Dashboard | ||
GET |
/dashboard/net-worth |
Calculate net worth |
| Market Data | ||
GET |
/market/search |
Search for stocks/crypto symbols |
GET |
/market/quote |
Get current price quote |
GET |
/market/chart |
Get historical price chart data |
Example Request:
curl -H "X-API-Key: your-key" \
https://api.finance.yourdomain.com/accountsAPI Version: 1.1.4
Client Version: 1.2.3
License: MIT
Maintained by: apptrackit
- API Architecture Documentation β Detailed documentation of the clean architecture pattern used in the API
- Deployment Script β Automated deployment with
./deploy.sh - Database Schema β See
api/schema.sqlfor complete database structure - PWA Configuration β See
client/vite.config.tsfor Progressive Web App setup

