FitTrack Pro is a Next.js fitness tracking application that combines Supabase authentication and persistence with AI-generated workout and meal plans.
- Email and password authentication with email verification
- Fitness profile and TDEE calculation
- Daily water intake tracking
- Personalized workout generation and completed-workout tracking
- Personalized daily meal-plan generation
- Weekly progress summaries
- Next.js 15, React 19, and TypeScript
- Tailwind CSS 4
- Supabase Authentication, Database, and Realtime
- OpenAI API
- Node.js built-in test runner
- Node.js 20 or newer
- A Supabase project with the tables expected by the application
- An OpenAI API key for workout and meal-plan generation
The versioned Supabase schema in supabase/migrations defines the application tables, constraints, indexes, and Row Level Security policies. Browser database access relies on those policies being applied to every environment.
-
Install dependencies:
npm install
-
Create a local environment file from the documented template:
cp .env.example .env.local
-
Fill in
.env.localwith your Supabase project values, application URL, and server-only OpenAI API key. -
Start the development server:
npm run dev
-
Open http://localhost:3000.
| Variable | Scope | Purpose |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Browser and server | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Browser and server | Supabase anonymous key; requires appropriate Row Level Security |
NEXT_PUBLIC_SITE_URL |
Browser and server | Application origin used for authentication redirects |
NEXT_APP_OPENAI_API_KEY |
Server only | OpenAI credential used to generate workouts and meal plans |
E2E_AUTH_EMAIL |
Local/CI test runner only | Optional dedicated Supabase test-user email for authenticated Playwright flows |
E2E_AUTH_PASSWORD |
Local/CI test runner only | Optional dedicated Supabase test-user password for authenticated Playwright flows |
E2E_MOCK_AI |
Local/CI test runner only | Set to 1 to make authenticated generation E2E tests use deterministic workout and meal-plan fixtures instead of OpenAI |
Never commit .env.local or real credentials. The checked-in .env.example contains placeholders only.
Validate required local or deployment variables without printing secret values:
npm run env:checkAdd the deployed application origin and /auth/confirm callback to the Supabase Authentication URL configuration. Password recovery sends users through /auth/confirm?next=/reset-password; the callback verifies either PKCE codes or email OTP token hashes and only permits local redirect paths.
The app exposes lightweight operational endpoints:
GET /api/healthreturns a non-sensitive uptime payload for load balancers and external monitors.GET /api/readinessverifies required environment variable names are configured and returns503when configuration is incomplete. It reports missing variable names only and never returns secret values.
Server-side failure paths should use the structured logger in app/lib/logger.ts instead of raw console.error calls. The logger redacts metadata keys that look like credentials, tokens, cookies, or secrets. Keep user-facing messages generic, and put only safe operational context such as route names, action names, booleans, status codes, and error codes into logs.
Generation actions are protected by Supabase authentication, Row Level Security, and a best-effort per-process rate limiter before costly workout or meal-plan generation runs. Production deployments should still enforce durable request rate limits at the hosting edge, API gateway, or Supabase layer to control cost and abuse across serverless instances.
This app includes a vercel.json configuration that applies baseline security headers to every route in Vercel deployments, including HSTS, frame denial, MIME-sniffing protection, a strict referrer policy, and a restrictive permissions policy. Keep these headers enabled for preview and production deployments unless a specific integration requires a reviewed exception.
Because Vercel serverless instances do not share in-memory state, keep the in-app generation limiter as a fast local guard and configure durable abuse controls at the Vercel edge for production. At minimum, add Vercel Firewall or WAF rules that rate-limit authenticated generation POST traffic and alert on repeated generation.rate_limited log events.
The supabase directory contains the local project configuration and versioned database migrations. The empty 20260611155633_remote_baseline.sql marker represents the existing dashboard-managed schema already recorded remotely. The following reconciliation migration safely hardens those existing tables, preserves food_logs, enables consistent Row Level Security, prevents duplicate daily records, and defines the atomic save_profile_with_tde database function.
Before applying the reconciliation migration, run supabase/preflight/20260611170000_reconcile_fitness_schema.sql in the linked project and verify every query returns no rows. Do not restore or push the removed empty-database initial migration against the existing project.
Install the Supabase CLI. This migration history is currently based on an existing dashboard-managed project: the empty baseline marker aligns remote history, while the reconciliation migration assumes the existing tables are present. Do not run supabase db reset against this history until the committed remote schema snapshot has been promoted into a reproducible baseline migration.
After reviewing the pending reconciliation migration, inspect and apply it to the linked remote project with:
supabase link --project-ref <project-ref>
supabase migration list --linked
supabase db push --dry-run
supabase db pushAfter changing the database schema, generate a temporary contract from the linked project and compare it with the checked-in TypeScript database contract:
supabase gen types typescript --linked > supabase/remote-database.types.tsWindows PowerShell 5.1 writes redirected output as UTF-16, which causes ESLint to report that the generated TypeScript file appears to be binary. Use an explicit UTF-8 encoding instead:
npx supabase gen types typescript --linked | Out-File -Encoding utf8 supabase/remote-database.types.tsThe temporary supabase/remote-database.types.ts comparison artifact is ignored by Git and ESLint. The checked-in database types intentionally include more specific JSON-column shapes used by the current application, so review regenerated JSON fields before replacing app/lib/database.types.ts and keep application validation aligned with the database contract.
Run the complete local quality gate:
npm run env:check
npm run check
npm run build
npm run test:e2eOr run checks individually:
npm run lint
npm run typecheck
npm testThe test command compiles the selected TypeScript source and tests into the ignored .test-dist directory, then runs them with Node's built-in test runner. The baseline suite covers authentication and profile schemas, TDEE calculations, generated workout and meal-plan validation, Supabase client contracts, and the required migration contract.
Playwright always runs the public authentication journeys. Authenticated protected-flow tests are included automatically only when both E2E_AUTH_EMAIL and E2E_AUTH_PASSWORD are set. Use a dedicated non-production Supabase user, keep those values in .env.local or CI secrets, and never commit real credentials. The authenticated setup stores browser state under the ignored playwright/.auth/ directory. Set E2E_MOCK_AI=1 with the authenticated credentials to run deterministic meal-plan and workout-generation E2E coverage without making real OpenAI requests.
| Command | Description |
|---|---|
npm run dev |
Start the development server with Turbopack |
npm run build |
Create an optimized production build |
npm run start |
Start a previously built production application |
npm run lint |
Lint the repository with ESLint |
npm run typecheck |
Run the TypeScript compiler without emitting files |
npm run env:check |
Validate required environment variable names without printing values |
npm test |
Compile and run the baseline unit tests |
npm run check |
Run lint, type-checking, and unit tests |
npm run test:e2e |
Run Playwright public journeys and, when E2E credentials are configured, authenticated protected-flow checks in Chromium |
npm run ci |
Run checks, production build, and end-to-end tests |
This repository is being hardened incrementally. The current baseline includes deterministic builds, explicit quality scripts, validated authentication recovery, profile and TDEE domains, user-local daily tracking, versioned Supabase schema and Row Level Security policies, documented environment setup, observability endpoints, and release controls. AI-generated workout and meal-plan output is now validated before persistence and regeneration is non-destructive. Public authentication journeys run in CI, authenticated Supabase protected-flow smoke tests run whenever dedicated E2E credentials are configured, and deterministic mocked-AI E2E coverage verifies generated workout and meal-plan persistence without spending model tokens. Upcoming work should focus on enabling Vercel Firewall/WAF rate-limit rules in production and wiring those events into broader abuse monitoring.
Deployment and rollback steps are documented in docs/release.md.