Files
Nox (OpenClaw) 434de9aa3e feat: production docker + documentation
- Backend Dockerfile: multi-stage build with venv, gunicorn+uvicorn workers, entrypoint runs alembic then gunicorn
- Frontend Dockerfile: multi-stage with npm ci, nginx:1.27-alpine runtime
- nginx.conf: gzip compression, security headers (X-Frame-Options, X-Content-Type-Options, etc.), static asset caching, correct API proxy preserving /api/ prefix
- docker-compose.yml: production config — db healthcheck, backend healthcheck, frontend depends_on backend healthy, no exposed backend port
- docker-compose.override.yml: dev hot-reload — uvicorn --reload with source mount, npm run dev on port 5173
- Rate limiting: slowapi middleware on /auth/login (10/min) and /auth/register (5/min)
- README.md: full documentation with architecture, quick start, API table, dev/prod instructions, tests
- .env.example: all variables documented with comments
- .gitignore: extended with *.pyc, *.cover, .ruff_cache, frontend/.vite, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 17:07:38 +00:00

5.3 KiB

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

# 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
# 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

# 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=<generated value>
# CORS_ORIGINS=["https://your-domain.com"]

Tests

# 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