A full-stack personal finance app to track budgets, categories, and transactions with a modern React UI and a Laravel API.
It includes user authentication, currency preferences with live exchange rates, responsive pages, and handy widgets like totals and pagination.
-
Authentication & Profile
- SPA-friendly authentication via Laravel Sanctum
/api/meprofile endpoint, password and profile updates- Default currency stored on the user model and editable via
/api/profile/currency
-
Budgets, Categories & Transactions
- Full CRUD for budgets and transactions
- Category lookup with server-side filtering
- Access control through Laravel policies
- Pagination and UI improvements for transactions
-
Currencies & Exchange Rates
- Integration with API Layer Exchange Rates Data for live currency conversion
- Snapshot storage and summary widgets in the dashboard
-
Frontend
- React 19 with React Router 7
- Reusable authentication context and API utilities
- Responsive design, animated carousel, and clean UI across all pages
| Layer | Stack |
|---|---|
| Frontend | React 19, React Router 7, React Slick (carousel) |
| Backend | Laravel 10, PHP 8.2+, Laravel Sanctum |
| Database | Any DB supported by Laravel (MySQL/PostgreSQL/SQLite) |
backend/ # Laravel API (controllers, models, policies, routes, migrations)
frontend/ # React app (pages, router, components, assets)
Key paths:
backend/routes/api.phpapp/Http/Controllers/*app/Actions/StoreRatesSnapshot.phpfrontend/src/Pages/*frontend/src/features/auth/AuthContext.jsxfrontend/src/lib/userApi.js
cd backend
cp .env .env
# configure DB_* in .env
composer install
php artisan key:generate
php artisan migrate
php artisan serveThe API uses Sanctum on protected routes such as /api/me, /api/budgets, /api/profile, /api/password, and /api/profile/currency.
This project uses the API Layer Exchange Rates Data service
to fetch real-time currency exchange rates for converting between different currencies and calculating totals.
You need to obtain a free API key from API Layer.
- Create an account on apilayer.com.
- Go to Dashboard → API Keys and copy your key.
- Add it to your
.envfile in the Laravel backend:
EXCHANGE_RATES_API_KEY=your_api_key_here
EXCHANGE_RATES_API_URL=https://api.apilayer.com/exchangerates_data/latest-
The backend fetches data from the API using the endpoint:
GET https://api.apilayer.com/exchangerates_data/latest?base=USD -
The API key is passed in the request header:
apikey: your_api_key_here-
Exchange rates can be stored in the database or used directly for conversions.
-
The Laravel action
StoreRatesSnapshotfetches and stores current rates,
enabling the app to display converted totals and summaries even offline.
$resp = Http::withHeaders([
'Accept' => 'application/json',
'apikey' => $key,
])
->connectTimeout(5)
->timeout(20)
->retry(3, 500, throw: false)
->withOptions(['force_ip_resolve' => 'v4'])
->get($url, [
'base' => strtoupper($base),
]);- The free API plan has a limited number of requests per month — check your quota in the dashboard.
- Change the base currency (e.g., EUR, RUB, CZK) using the
basequery parameter. - This feature powers the currency selector and total summary widgets on the frontend.
cd frontend
npm install
npm run dev # or npm startCreate a .env file in frontend/ if you need to set a custom API URL:
VITE_API_URL=http://127.0.0.1:8000The app includes Home, Dashboard, and Profile pages with currency settings and summaries.
All routes below require authentication unless stated otherwise:
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/me |
Returns current user and default currency |
PATCH |
/api/profile |
Update user profile |
PATCH |
/api/password |
Change password |
PATCH |
/api/profile/currency |
Set default currency |
GET / POST / DELETE |
/api/budgets |
Manage budgets |
GET / POST / DELETE |
/api/transactions |
Manage transactions |
GET |
/api/categories |
Get categories list |
Demo images are available in frontend/src/assets:
login.jpgbudget.jpgtransaction.jpgcurrency.jpg- and more....
- Add charts & statistics page
- CSV import/export
- Improved category management
Pull requests are welcome!
For major changes, please open an issue first to discuss what you’d like to add or modify.
Licensed under the Apache 2.0 license.
See LICENSE for details.