# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Development Commands ### Start Everything ```bash ./develop.sh # starts PostgreSQL (Docker), backend (uvicorn), and frontend (vite) together ``` ### Backend ```bash cd backend source .venv/bin/activate uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ruff check . # lint ruff format . # format pytest # run tests ``` ### Frontend ```bash cd frontend npm run dev # dev server on :5173 npm run build # production build npm run lint # ESLint ``` ### Database ```bash docker compose up -d # start PostgreSQL with pgvector on :5432 ``` ## Architecture Full-stack health/fitness tracker with AI-powered nutrition analysis and plan generation. **Stack:** FastAPI (Python) + React 19 (TypeScript) + PostgreSQL/pgvector + DSPy + OpenAI GPT-4o ### Backend (`/backend`) - `app/main.py` — FastAPI app, CORS config, router mounting - `app/api/v1/endpoints/` — Route handlers: `login`, `users`, `nutrition`, `health`, `plans` - `app/models/` — SQLModel ORM models (User, HealthMetric, HealthGoal, FoodLog, FoodItem, Plan) - `app/ai/` — DSPy modules: `nutrition.py` (food analysis + image analysis), `plans.py` (personalized plan generation) - `app/core/ai_config.py` — DSPy LM configuration (GPT-4o mini) - `app/api/deps.py` — FastAPI dependencies for auth and DB session injection ### Frontend (`/src`) - `App.tsx` — React Router routes; all routes except `/login` are wrapped in `ProtectedRoute` - `api/client.ts` — Axios instance with base URL from `VITE_API_URL`; Bearer token auto-attached via interceptor from localStorage - `context/AuthContext.tsx` — Auth state (token, user); token persisted to localStorage - `pages/` — One page component per route (Dashboard, Nutrition, Health, Plans, Profile) - `components/catalyst/` — Reusable UI component library (buttons, inputs, tables, dialogs, etc.) ### Auth Flow OAuth2 password flow → JWT (HS256, 8-day expiry) → stored in localStorage → Axios interceptor injects header on every request. ### AI Modules (DSPy) Both AI modules use chain-of-thought (`dspy.ChainOfThought`) via GPT-4o mini: - **Nutrition:** Analyzes food text/images → macro breakdown accounting for hidden calories (oils, sauces) - **Plans:** Generates personalized diet + exercise plans from user profile data ### Environment Variables See `.env.example`. Required: `DATABASE_URL`, `OPENAI_API_KEY`, `SECRET_KEY`, `POSTGRES_*` vars. Frontend uses `VITE_API_URL` (defaults to `http://localhost:8000/api/v1`). ## Push Notifications ### Testing push notifications **Always use the production build** — never test push notifications against `npm run dev`. The dev server's hot-reloading reinstalls the service worker on every reload, which invalidates push subscriptions (FCM returns 410 Gone). ```bash cd frontend npm run build npx serve dist -p 5173 -s # -s = SPA mode (falls back to index.html) ``` Then in the browser: 1. DevTools → Application → Service Workers → Unregister any old SW 2. Hard-refresh (`Cmd+Shift+R`) to install the fresh `sw.js` 3. Profile → Notifications → toggle ON to create a fresh subscription 4. Use "Send test" button or trigger via backend ### If push notifications stop working - Check `chrome://gcm-internals/` — Connection State must be **CONNECTED** (not CONNECTING) - If disconnected, fully quit and restart Chrome (`Cmd+Q`) - Clear stale DB subscriptions: `docker compose exec db psql -U user -d healthyfit -c "DELETE FROM pushsubscription;"` - Re-subscribe after restarting