TradeTrackr is a Personal Finance + Trading Performance Tracker built with Vite + React and Supabase.
It’s designed to feel fast and smooth while staying secure by default (RLS + safe auth).
- Google sign-in (OAuth)
- Email OTP sign-in (one-time code; avoids fake-email “logins”)
- Email + password sign-in
- Trading journal (daily P&L, cumulative P&L, running capital, loss guard)
- Expenses & income tracking
- Broker connect (manual + future API/CSV flows)
- AI assistant (floating support-style widget via Supabase Edge Function)
- Frontend: Vite + React 19 + TypeScript
- Routing: React Router (SPA)
- UI: Tailwind CSS + shadcn/ui (Radix primitives)
- State: Zustand
- Forms/Validation: react-hook-form + Zod
- Backend: Supabase (Auth + Postgres + Row Level Security)
- AI: Supabase Edge Function (
ai) → Groq (server-side key)
- Vite gives fast local dev and optimized production builds
- SPA navigation (React Router) avoids full page reloads
- Zustand keeps global state lightweight (less re-render churn)
- Supabase RLS simplifies backend logic and reduces extra service layers
- Mobile-first layouts for table-heavy screens:
TradingandExpensesuse card layouts on small screens
Auth is powered by Supabase Auth:
- Google OAuth (recommended): identity verified by Google
- Email OTP sign-in: code is emailed; sign-in only works for existing accounts (
shouldCreateUser: false) - Email + Password: supported for users who prefer passwords
The app ensures there’s always a profiles row for each signed-in user using upsert on profiles.id.
This prevents issues like duplicate key value violates unique constraint "profiles_pkey".
Supabase Postgres is the source of truth.
profilestrade_entriesexpensesbrokerscategoriesbroker_sync_logsmonthly_summariesai_summaries
- RLS enabled on all tables
- Policies isolate data by user using
auth.uid() - The
authenticatedrole has table privileges (GRANTs), and RLS does the real protection
supabase/migrations/20260508051040_create_tradetrackr_schema.sql
AI runs through a Supabase Edge Function so the Groq key is never shipped to the client:
- Function: supabase/functions/ai/index.ts
- Client helper: src/lib/ai.ts
- UI widget: src/components/ai/AiAssistantWidget.tsx (mounted globally in layout)
- Edge Function is deployed with
verify_jwt: true - Set Groq key as a Supabase secret:
GROQ_API_KEY
The Edge Function supports OPTIONS preflight and sets CORS headers for browser requests.
- Install dependencies
npm install- Create
.env(do not commit it)
VITE_SUPABASE_URL=https://<your-project-ref>.supabase.co
VITE_SUPABASE_ANON_KEY=<your_anon_key>- Run
npm run devThis is a React Router SPA, so deep links like /dashboard must rewrite to /.
The repo includes vercel.json rewrites.
Set:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
In Supabase:
- Auth → URL Configuration
- Add redirect URLs like
https://<your-domain>/dashboard
- Add redirect URLs like
- Google provider
- Google Cloud Console redirect URI:
https://<your-project-ref>.supabase.co/auth/v1/callback
- Google Cloud Console redirect URI:
In Supabase Edge Functions → Secrets:
GROQ_API_KEY