Last updated: 2026-03-28
This file is the repo-root operating guide for coding agents working in SparkyFitness. Use it to orient at the monorepo level, choose the correct package, and find verified commands quickly.
When a package-level guide has deeper or conflicting instructions, follow the package guide over this file. In this repo that usually means AGENTS.md when present, otherwise the package's CLAUDE.md.
- Start from this file when work begins at the repository root or spans multiple packages.
- Move into the affected package before doing most implementation work or validation.
- Treat this file as a monorepo guide, not a full product specification.
- Do not invent root-level app workflows. Root
package.jsonis mostly tooling (husky,lint-staged,prettier), not an app entrypoint. - Repo-root
CLAUDE.mdcurrently just points back to this file.
SparkyFitnessFrontend/- React 19 + Vite web app.SparkyFitnessServer/- Node.js + Express 5 backend API with PostgreSQL.SparkyFitnessMobile/- React Native 0.81.5 + Expo SDK 54 mobile app.shared/- workspace package for shared TypeScript code, Zod schemas, and timezone helpers exported through@workspace/shared.docs/- Nuxt 3 / Docus documentation site.SparkyFitnessMCP/- standalone TypeScript MCP server package.SparkyFitnessGarmin/- Python Garmin integration service.docker/,helm/,.github/- deployment, infrastructure, and CI/CD assets.db_schema_backup.sql- repo-root database schema snapshot that should stay aligned with server migrations.docker/.env.example- tracked environment variable template commonly copied to repo-root.env.
- Start at repo root only to identify scope, inspect shared context, or coordinate cross-package changes.
- Run package commands from the package directory you are changing.
- If a task crosses frontend, server, mobile, or
shared/boundaries, read each relevant package guide before editing. pnpm-workspace.yamlcurrently listsfrontend,SparkyFitnessFrontend,shared,SparkyFitnessMobile,SparkyFitnessServer, anddocs.- Only
SparkyFitnessFrontend/exists on disk right now; treatfrontendin the workspace file as a legacy entry unless the task is specifically about workspace cleanup. SparkyFitnessMCP/andSparkyFitnessGarmin/are outside the currentpnpmworkspace. Inspect their local manifests and scripts before working there.shared/is a library package, not an app. Validate shared changes from the consuming package(s) when needed.
pnpm dev
pnpm run typecheck
pnpm run lint
pnpm run format:check
pnpm run validate
pnpm run build
pnpm test
pnpm run test:cipnpm run validateruns typecheck, lint, and Prettier check together.- Vite dev server runs on port
8080and proxies API traffic to the backend on3010.
pnpm start
pnpm run typecheck
pnpm run lint
pnpm run lint:fix
pnpm test
pnpm run test:watch
pnpm run test:coverage
pnpm run test:ci- Backend default port is
3010unlessSPARKY_FITNESS_SERVER_PORToverrides it. - Use
pnpmin this package. Older docs may still shownpm, but the repo is apnpmworkspace and these scripts are verified inpackage.json. pnpm testalready includesNODE_OPTIONS='--experimental-vm-modules'.
pnpm start
pnpm run ios
pnpm run android
pnpm run lint
pnpm run test:run -- --watchman=false --runInBand
pnpm exec jest --watchman=false --runInBand <test-path>
pnpm exec tsc --noEmit
npx expo prebuild -c- In sandboxed macOS agent runs, avoid bare
pnpm testor barejest; Watchman can fail. - For targeted mobile Jest runs, prefer
pnpm exec jest --watchman=false --runInBand <test-path>. - Run
npx expo prebuild -cafter native dependency or native config changes.
pnpm dev
pnpm run build
pnpm run generate
pnpm run preview
pnpm run lintpnpm run dev
pnpm run build
pnpm start
pnpm test- Web: single-page React app built with Vite, Tailwind, TanStack Query, and route-level pages.
- API: Express backend with PostgreSQL, Better Auth, RLS-aware database access, SQL migrations, and third-party provider integrations.
- Mobile: Expo app that syncs HealthKit / Health Connect data and consumes the same backend APIs.
- Shared: reusable TypeScript exports in
shared/for schemas, constants, and timezone/day-string helpers. - Docs: separate Nuxt / Docus site for user-facing documentation.
- MCP: TypeScript package for the project's custom Model Context Protocol server.
- Garmin: standalone Python service for Garmin-related integration work.
- Frontend local development proxies
/api,/api/withings, and/health-datato the backend on localhost. - Backend APIs are generally rooted at
/api. - Mobile health sync ultimately targets
POST /api/health-dataon the server side. Keep the frontend proxy path/health-datadistinct from the server API path.
- The tracked environment template lives at
docker/.env.example. - Local development and many deployments copy that template to repo-root
.env. - Server runtime secrets are expected in the repo-root
.envwhen working fromSparkyFitnessServer/. - The server can also load secrets from files via
SparkyFitnessServer/utils/secretLoader.js.
db_schema_backup.sqlis the repo-root reference schema snapshot.- New server migrations belong in
SparkyFitnessServer/db/migrations/. - Migration filenames must follow
YYYYMMDDHHMMSS_description.sql. - If you add or change a migration, also update repo-root
db_schema_backup.sqlin the same change. - If you add a database table or change user-visible access behavior, also update
SparkyFitnessServer/db/rls_policies.sql. - Treat the RLS policy file and schema snapshot as mandatory maintenance, not optional cleanup.
- Prefer the shared helpers in
shared/src/utils/timezone.ts, exported through@workspace/shared, for day-string and timezone-aware date logic. - Use
isDayString,addDays,compareDays,dayToPickerDate, andpickerDateToDayforYYYY-MM-DDcalendar-day strings. - Use
todayInZone,instantToDay,instantHourMinute,dayToUtcRange, anddayRangeToUtcRangewhen a user's timezone matters. - On the server, load the user's timezone with
SparkyFitnessServer/utils/timezoneLoader.jsbefore deriving "today", bucketing timestamps by day, or building day-based query ranges. - Avoid ad hoc UTC date extraction such as
toISOString().split('T')[0]for user-facing or business-logic dates. That pattern silently shifts dates near timezone boundaries and is not a substitute for timezone-aware day handling. - Treat
YYYY-MM-DDvalues as calendar-day strings, not as UTC-midnight timestamps. Convert to UTC ranges only at the boundary where the database or an external API needs instants. - If you touch older code that still derives day strings with
toISOString().split('T')[0], prefer migrating that path to the shared helpers instead of copying the pattern forward. - Shared timezone helpers are currently exercised in
SparkyFitnessServer/tests/timezone.test.js; update or extend those tests when changing the shared date/time behavior.
- Server auth supports cookie-backed sessions and API keys.
- Mobile supports both API key auth and session-token auth, plus optional proxy headers for reverse-proxy setups.
- If auth behavior changes in one client, check whether web and mobile both rely on the same backend contract.
- Frontend bug fix from repo root:
move into
SparkyFitnessFrontend/, read its package guide, then run the relevant web validation command. - Server migration or new table:
move into
SparkyFitnessServer/, add the migration, and updatedb/rls_policies.sqlplus repo-rootdb_schema_backup.sqlin the same change. - Shared schema or timezone helper work:
move into
shared/, update exports insrc/index.tsif needed, then validate from the consuming package(s). - Mobile health sync debugging:
move into
SparkyFitnessMobile/, read the mobile guide, then inspect sync services and health API usage before testing with Watchman-safe Jest commands. - Docs change:
move into
docs/, inspectpackage.json, then use the Nuxt/Docus commands above. - MCP server change:
move into
SparkyFitnessMCP/, inspectpackage.json, then use its local build or dev commands.
- Repo-root alias:
CLAUDE.mdpoints to this file. - Frontend deep guide:
SparkyFitnessFrontend/CLAUDE.md - Server package guide:
SparkyFitnessServer/AGENTS.md - Mobile package guide:
SparkyFitnessMobile/AGENTS.md
For shared/, docs/, SparkyFitnessMCP/, and SparkyFitnessGarmin/, there is currently no package-level AGENTS.md. Inspect the local manifest, README, and source layout before making package-specific assumptions.
- If this file and a package-level guide disagree, the package-level guide wins for work inside that package.
- In practice, prefer package
AGENTS.mdwhen present and fall back to packageCLAUDE.mdwhen it is the only guide. - If a task spans multiple packages, combine this root guide with each affected package guide instead of relying on one document alone.