Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

💸 Expensa — Full-Stack Expense Tracker

A modern, responsive expense tracker with a beautiful analytics dashboard, built with React (Vite) + Tailwind CSS on the front end and FastAPI + SQLAlchemy + SQLite on the back end.

React Vite Tailwind FastAPI SQLite


✨ Features

  • Analytics dashboard — headline stat cards (total spent, this month, average per day, top category), a category donut chart, and a monthly spending bar chart.
  • Category-wise spending with an accessible, colorblind-safe palette that reads consistently in light and dark mode.
  • Monthly summaries computed server-side from the data.
  • Search & filtering — full-text search over title/notes, filter by category and date range, and sort by date / amount / title / category (asc/desc).
  • Full CRUD — add, edit, and delete expenses with inline validation and an undoable-feeling confirm dialog for deletes.
  • Responsive design — a sidebar layout on desktop that collapses to a mobile drawer; tables become stacked cards on small screens.
  • Dark mode — system-aware, one-click toggle, persisted to localStorage, with no flash of the wrong theme on load.
  • Toast notifications for every mutation.
  • Sample data seeded automatically on first run so the dashboard is never empty.

🧱 Tech stack

Layer Tech
Frontend React 18, Vite 6, Tailwind CSS 3, React Router, Recharts, lucide-react, date-fns
Backend FastAPI, SQLAlchemy 2, Pydantic 2, Uvicorn
Database SQLite

📁 Project structure

expense-tracker/
├── backend/
│   ├── app/
│   │   ├── main.py        # FastAPI app + routes
│   │   ├── database.py    # SQLAlchemy engine / session
│   │   ├── models.py      # Expense ORM model
│   │   ├── schemas.py     # Pydantic request/response schemas
│   │   ├── crud.py        # Query + mutation logic, summary stats
│   │   └── seed.py        # First-run sample data
│   └── requirements.txt
├── frontend/
│   ├── src/
│   │   ├── components/    # Layout, charts, table, modal, filters, …
│   │   ├── pages/         # Dashboard, Expenses
│   │   ├── context/       # Theme + toast providers
│   │   └── lib/           # api client, formatting, color palette
│   ├── index.html
│   └── package.json
└── README.md

🚀 Getting started

Prerequisites

  • Python 3.11+ (developed on 3.14)
  • Node.js 18+

1. Backend

cd backend
python -m venv .venv

# Activate the virtualenv
source .venv/Scripts/activate     # Git Bash on Windows
# .venv\Scripts\activate          # PowerShell / CMD on Windows
# source .venv/bin/activate       # macOS / Linux

pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000

The API is now at http://127.0.0.1:8000 and interactive docs at http://127.0.0.1:8000/docs. On first run it creates expenses.db and seeds it with ~90 sample expenses.

2. Frontend

In a second terminal:

cd frontend
npm install
npm run dev

Open http://localhost:5173. Vite proxies /api to the backend on port 8000, so both run happily side by side with no CORS setup.


🔌 API reference

Base path: /api

Method Endpoint Description
GET /health Health check
GET /expenses List expenses. Query params: search, category, start_date, end_date, sort_by (date|amount|title|category), order (asc|desc)
POST /expenses Create an expense
GET /expenses/{id} Get a single expense
PUT /expenses/{id} Update an expense
DELETE /expenses/{id} Delete an expense
GET /categories Distinct category names
GET /stats/summary Totals, this-month total, daily average, per-category and per-month breakdowns

Example expense payload:

{
  "title": "Grocery run",
  "amount": 42.5,
  "category": "Food",
  "notes": "Weekly shop",
  "date": "2026-07-02T10:30:00"
}

🏗️ Production build

cd frontend
npm run build      # outputs to frontend/dist

Serve the built assets behind the same origin as the API (or point a reverse proxy at both) so the /api calls resolve without CORS.


📝 Notes

  • The SQLite database (backend/expenses.db) is git-ignored and regenerated with fresh sample data on first run — delete it to reseed.
  • Chart colors come from a validated, colorblind-safe categorical palette; identity is never conveyed by color alone (every series is directly labelled).

📄 License

MIT — do whatever you like.

Releases

Packages

Contributors

Languages