A personal finance web app for tracking income and expenses, built with Vue 3 and TailwindCSS v4. Connects to a REST API backend.
- Summary cards — Income, Expenses, Net Balance, and Savings Rate for the selected period
- Period filter — 7 preset ranges: This Month, Last Month, Last 3/6 Months, This Year, This FY, Last FY (Indian financial year Apr–Mar)
- Top Categories — Progress-bar widget showing top 5 expense and income categories side by side
- Charts (ApexCharts):
- Expense breakdown by category (donut)
- Income vs Expense over time (bar)
- Expense breakdown by payment method (donut)
- Recent Transactions list with quick links
- Full skeleton loaders on initial load; overlay spinner on period switch
- Paginated transaction list with server-side filtering by:
- Type (income / expense)
- Category
- Payment method
- Date range
- Collapsible filter panel on mobile; always-visible on desktop
- Active filter count badge
- Add / Edit transactions via a modal form (amount, type, category, payment method, date, notes)
- Delete with confirmation dialog
- CSV export of the current filtered result set
- Responsive: table layout on desktop, card layout on mobile
- Categories — Create, rename (inline), and delete custom transaction categories
- Payment Methods — Create, rename (inline), and delete payment methods (e.g. Cash, UPI, Credit Card)
- View account details (name, email, phone, member since)
- Edit first name, last name, and email with Zod-validated form
- Change password with current-password verification
- Delete account with confirmation
- Phone + OTP login flow
- Profile setup on first login (name, email)
- Route guards — protected pages redirect to login; authenticated users are redirected away from login
- Dark mode — class-based, persisted across sessions
- Mobile-first layout with bottom navigation bar and floating action button for adding transactions
- Toast notifications for success and error feedback
- Responsive sidebar navigation on desktop
| Layer | Library / Tool |
|---|---|
| Framework | Vue 3 (Composition API, <script setup>) |
| Language | TypeScript |
| Build | Vite 7 |
| Styling | TailwindCSS v4 |
| State Management | Pinia |
| Routing | Vue Router 5 |
| HTTP Client | Axios |
| Forms & Validation | VeeValidate + Zod |
| Charts | ApexCharts via vue3-apexcharts |
| Utilities | @vueuse/core (breakpoints, composables) |
| Linting | ESLint + oxlint |
| Formatting | Prettier |
- Node.js 20+
- A running instance of the backend API
# Install dependencies
npm install
# Create environment file — set VITE_API_BASE_URL to your backend URL
echo "VITE_API_BASE_URL=http://localhost:8000" > .envnpm run devThe dev server proxies /v1 requests to http://localhost:8000 (configurable in vite.config.ts).
npm run buildOutput is written to dist/.
npm run type-check
npm run lintThe app is pre-configured for hosting at /<repo-name>/ on GitHub Pages (base: '/expense-web/' in vite.config.ts).
A public/404.html redirect shim handles deep-link refreshes so Vue Router routes work correctly after deploy.
Set the following repository secret before running the deploy workflow:
| Secret | Value |
|---|---|
VITE_API_BASE_URL |
Production API base URL |