A modern, full-stack personal finance dashboard. Track income & expenses, manage an investment portfolio with live prices, and get LLM-powered monthly insights and a 0–100 financial health score.
| Layer | Tech |
|---|---|
| Frontend | React (Vite) + Tailwind CSS + Recharts |
| Backend | FastAPI (Python) |
| Database | Supabase (PostgreSQL) |
| Stock data | yfinance |
| AI (primary) | Groq — llama-3.1-70b-versatile |
| AI (secondary) | Anthropic — claude-opus-4-5 |
| Frontend deploy | Vercel |
| Backend deploy | Render |
fintrack/
├── frontend/ # React + Vite + Tailwind app
└── backend/ # FastAPI app
└── app/
├── routers/ # budget, investments, stocks, insights
├── models/ # Pydantic models + canonical category list
├── services/ # ai_service.py, stock_service.py
└── db/ # Supabase client + schemas.sql
After backend and frontend setup, start both servers in one terminal:
chmod +x dev.sh # once
./dev.shPreflight checks warn about missing .env files, dependencies, or ports already in use. Use ./dev.sh --force to start when ports are busy.
- Create a new project at supabase.com.
- Open the SQL editor and run the contents of
backend/app/db/schemas.sqlto create all tables and indexes. - From Project Settings → API, copy:
Project URL→SUPABASE_URLanon(orservice_rolefor write access from a trusted backend) →SUPABASE_KEY
The backend uses the standard PostgREST endpoints, so either key works for local dev. Use
service_roleonly in trusted server environments.
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtcp .env.example .envFill in the values:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_supabase_key
GROQ_API_KEY=your_groq_api_key- Get a free Groq API key at console.groq.com. The app uses Groq only by default (
app/services/ai_service.py). To use Anthropic instead, uncomment the Claude code there and addANTHROPIC_API_KEYto.env.
uvicorn app.main:app --reload --port 8000The API will be available at http://localhost:8000. Health check: GET /health. Interactive docs at http://localhost:8000/docs.
POST /budget/income Create or update monthly income
GET /budget/income/{YYYY-MM} Get income for a month
POST /budget/expenses Log an expense
GET /budget/expenses/{YYYY-MM} List expenses for a month
DELETE /budget/expenses/{id} Delete an expense
GET /budget/summary/{YYYY-MM} Income/spent/savings/breakdown
POST /budget/caps Upsert a budget cap
GET /budget/caps/{YYYY-MM} List caps for a month
GET /budget/categories Canonical category list
POST /investments/transactions
GET /investments/transactions
DELETE /investments/transactions/{id}
GET /investments/portfolio Aggregated, live-priced positions
GET /stocks/search?ticker=NVDA Live ticker lookup
POST /insights/generate/{YYYY-MM} Generate + store spending insights
GET /insights/{YYYY-MM} Stored insights
POST /insights/health-score/{YYYY-MM}
GET /insights/health-score/{YYYY-MM}
cd frontend
npm installcp .env.example .env
# .env content:
# VITE_API_BASE_URL=http://localhost:8000npm run devApp will open at http://localhost:5173.
- Dashboard — top-level stats, donut chart, recent expenses & transactions, health score ring.
- Budget — income card, expense form, expense table, category breakdown with cap progress, cap manager. Month selector at the top.
- Investments — transaction form with live ticker lookup, full portfolio table with live prices and color-coded gain/loss, summary bar.
- Insights — generate / regenerate AI insights and the financial health score per month.
Target stack: Render Free (backend) + Vercel (frontend). Push this repo to GitHub first (shaunn17/FinTrack-AI).
Option A — Blueprint (recommended) — uses render.yaml at the repo root:
- Open Render Blueprints → New Blueprint Instance.
- Connect
shaunn17/FinTrack-AI, branchmaster. Blueprint path:render.yaml. - When prompted for secrets, set
SUPABASE_URL,SUPABASE_KEY, andGROQ_API_KEY. - Deploy. Note the service URL (e.g.
https://fintrack-api.onrender.com).
The blueprint sets plan: free so you are not billed for the web service. If Blueprint import asks for payment info, confirm plan: free is present in render.yaml and re-sync.
Option B — Manual Web Service (same settings, no Blueprint):
- New → Web Service → connect the GitHub repo.
- Root directory:
backend/. Runtime: Python 3. - Instance type: Free (not Starter).
- Build:
pip install --upgrade pip && pip install -r requirements.txt - Start:
uvicorn app.main:app --host 0.0.0.0 --port $PORT - Health check path:
/health - Environment variables:
SUPABASE_URL,SUPABASE_KEY,GROQ_API_KEY(plusANTHROPIC_API_KEYonly if you re-enable Claude in code).
Python version is pinned via backend/.python-version (3.13) and PYTHON_VERSION in render.yaml. Render does not read Heroku-style runtime.txt.
Free tier: the API sleeps after ~15 minutes of inactivity; the first request after that may take 30–60s (cold start).
- Import the repo at vercel.com, set the project root to
frontend/. - Framework preset: Vite.
- Build command:
npm run build. Output directory:dist. - Environment variable:
VITE_API_BASE_URL=https://fintrack-api.onrender.com(your Render URL, no/apisuffix). - Redeploy after the backend URL is live. SPA routing is handled by
frontend/vercel.json.
Hard-coded on both the frontend (src/styles/theme.js) and backend (app/models/budget.py):
GROCERIES, SUBSCRIPTIONS, RENT, UTILITIES, TRANSPORT,
DINING_OUT_FOOD, ENTERTAINMENT, STUDENT_LOANS_DEBT, MISCELLANEOUS
- Voice-to-text expense and investment entry (e.g. "Add my investment in NVIDIA for $500 with 2 shares at $250 on April 1st").
- Spending vs investment correlation view.
- Anomaly detection on transactions vs historical baseline.
- Natural language expense entry ("$12 coffee this morning" → auto-categorized).
- Migration from Supabase free tier when data grows.
MIT — do whatever you want with it.