# Budget Tracker A personal finance web application to track income, expenses, and budgets with analytics and CSV/PDF export. --- ## Stack | Layer | Technology | |-----------|-----------------------------------------------------| | Backend | FastAPI 0.115, SQLAlchemy 2.0 async, Alembic | | Database | PostgreSQL 16 | | Frontend | React 18, TypeScript, Vite, Tailwind CSS, Radix UI | | Charts | Recharts | | Export | CSV (native), PDF (WeasyPrint) | | Server | Gunicorn + Uvicorn workers, Nginx 1.27 | --- ## Quick Start ```bash # 1. Copy and configure environment cp .env.example .env # 2. Start all services (production mode) docker compose up -d # App is available at http://localhost # API docs at http://localhost/api/v1/docs ``` > The backend automatically runs `alembic upgrade head` on startup. --- ## Architecture ``` ┌─────────────┐ ┌──────────────────┐ ┌──────────────┐ │ Browser │──80──▶│ Nginx (frontend) │──/api/▶│ FastAPI │ └─────────────┘ │ serves SPA dist │ │ (gunicorn) │ └──────────────────┘ └──────┬───────┘ │ ┌──────▼───────┐ │ PostgreSQL │ └──────────────┘ ``` - **Frontend**: React SPA served by Nginx. All `/api/*` requests are proxied to the backend. - **Backend**: FastAPI with async SQLAlchemy. Exposes REST API under `/api/v1`. - **Database**: PostgreSQL with Alembic migrations applied at container start. --- ## API Endpoints Interactive docs (Swagger UI): `http://localhost/api/v1/docs` | Module | Prefix | Description | |--------------|-------------------------|------------------------------------| | Auth | `/api/v1/auth` | Register, login, refresh, logout | | Transactions | `/api/v1/transactions` | CRUD + pagination + filters | | Categories | `/api/v1/categories` | Income / expense categories | | Budgets | `/api/v1/budgets` | Monthly budgets + rollover | | Dashboard | `/api/v1/dashboard` | Monthly summary + charts data | | History | `/api/v1/history` | Year-over-year analytics | | Export | `/api/v1/export` | CSV and PDF export | | Health | `/health` | Liveness probe | --- ## Development (hot-reload) The `docker-compose.override.yml` is automatically merged in dev, enabling: - Backend: `uvicorn --reload` with source code mounted - Frontend: `npm run dev` (Vite HMR) on port 5173 ```bash # Start dev environment cp .env.example .env docker compose up # Backend API: http://localhost:8000 # Frontend dev server: http://localhost:5173 # API docs: http://localhost:8000/api/v1/docs ``` --- ## Production ```bash # Use only the base compose file (no override) docker compose -f docker-compose.yml up -d # Generate a secure SECRET_KEY python -c "import secrets; print(secrets.token_hex(32))" # Set in .env: # SECRET_KEY= # CORS_ORIGINS=["https://your-domain.com"] ``` --- ## Tests ```bash # Backend tests cd backend pip install -r requirements.txt pytest # With coverage pytest --cov=app --cov-report=term-missing # Frontend type check cd frontend npm run build # tsc -b + vite build ``` --- ## Project Structure ``` budget-tracker/ ├── backend/ │ ├── app/ │ │ ├── auth/ # JWT auth (register, login, refresh, logout) │ │ ├── models/ # SQLAlchemy ORM models │ │ ├── routers/ # FastAPI routers (transactions, budgets, …) │ │ ├── schemas/ # Pydantic request/response schemas │ │ ├── services/ # Business logic layer │ │ ├── config.py # Settings (pydantic-settings) │ │ ├── database.py # Async engine + session factory │ │ └── main.py # App factory + middleware │ ├── alembic/ # Database migrations │ ├── tests/ # pytest test suite │ ├── Dockerfile # Multi-stage build (venv → slim runtime) │ └── entrypoint.sh # alembic upgrade head → gunicorn └── frontend/ ├── src/ │ ├── api/ # Axios client + API functions │ ├── components/ # Shared UI components │ ├── hooks/ # React Query hooks │ ├── pages/ # Route-level page components │ └── stores/ # Zustand auth store ├── Dockerfile # Multi-stage build (npm ci → nginx) └── nginx.conf # Gzip, security headers, SPA fallback, API proxy ```