SyncGaze is a multi-language eye-tracking training and analytics stack. The Vite + React frontend drives onboarding → calibration → training → results → AI reports, while the Node backend handles CSV uploads, survey storage, and Anthropic-powered reports. Optional Python services cover ML score prediction and Cloud Run ingestion.
frontend/– main Vite app (React + TypeScript) with WebGazer tracking, dashboard/results/report pages, bilingual UI (ko/en), Firebase Auth, and session persistence.backend/– Express API backed by firebase-admin for CSV uploads, survey writes, and Claude-based performance reports.cloudrun/– Python Cloud Run service that ingests Storage CSVs and writes joined summaries to Firestore/BigQuery.ml_inference_function/– Python HTTP function that returnspredictedScorefor a session; wire it viaVITE_PREDICTION_ENDPOINT.analysis/– offline scripts/notebooks for feature extraction and model training.tracker-app/– original CRA prototype kept for reference only.functions/– firebase-functions friendly copy of the backend routes (usebackend/for local/dev).
SyncGaze/
├─ frontend/ # Vite app (React + TS)
│ ├─ src/
│ │ ├─ pages/ # Landing, Auth, Dashboard, Calibration, Training, Results, Report, etc.
│ │ ├─ features/
│ │ │ ├─ onboarding/ # Survey, consent helpers & UI
│ │ │ └─ tracker/ # Calibration components, constants, types
│ │ ├─ state/ # Contexts: trackingSession, auth, language, settings
│ │ ├─ hooks/ # Webgazer + tracking utilities
│ │ ├─ services/ # API helpers (reports, predictions)
│ │ ├─ utils/ # analytics, exports, remote session storage
│ │ └─ __tests__/ # Unit/UI specs (Vitest + RTL)
│ ├─ cypress/ # E2E specs (trackerFlow, errorHandling)
│ └─ public/ # static assets
├─ backend/ # Express API (upload CSV, survey, report proxy)
│ └─ src/routes/ # uploadCsv, submitSurvey, generateReport
├─ cloudrun/ # Python CSV ingestor for Firestore/BigQuery
├─ ml_inference_function/ # Python HTTP function for predictedScore
├─ analysis/ # Data prep/model training scripts
└─ tracker-app/ # Legacy CRA prototype
Prereq: Node 18+.
cd frontend && npm install- Copy
.env.exampleto.envand fill:VITE_FIREBASE_*– Firebase client keys (required)VITE_API_BASE_URLorVITE_BACKEND_URL– URL of the Node backend for CSV upload/report generationVITE_PREDICTION_ENDPOINTorVITE_PERFORMANCE_MODEL_ENDPOINT– optional ML scoring endpoint (falls back to heuristic when absent)
- Run
npm run devto start Vite,npm run buildfor production,npm run previewto serve the bundle. - Tests:
npm run test,npm run test:watch,npm run test:e2e,npm run test:e2e:open(Vitest + Cypress, seefrontend/cypress/e2e).
- Auth + onboarding: email/password, Google, or anonymous sign-in (
AuthPage), bilingual copy viaLanguageProvider, survey + consent steps gate access and sync to Firestore withsaveSurveyAndConsent. - Calibration + training: WebGazer-backed calibration (
CalibrationPage) with webcam gating, validation, andRECALIBRATION_THRESHOLDenforcement;TrainingPagerecords gaze/mouse/target telemetry. - Results + storage:
ResultsPagecomputes analytics (calculatePerformanceAnalytics), exports CSV viaexportSessionData, optionally uploads to the backend/Storage, and persists sessions to Firestore withsaveSessionForUser(including leaderboard opt-in and predicted score). - Insights: dashboard, history, and leaderboard pages read from Firestore (
SessionRemoteHydratorhydrates on login).ReportPagecalls the backend to generate Anthropic-based coaching reports;predictionServiceuses the ML endpoint when configured and otherwise falls back to a deterministic score.
- Unit/UI: Vitest + React Testing Library; tests colocated under
frontend/src/**/__tests__and page-level specs. Runnpm run testornpm run test:watch. - E2E: Cypress specs in
frontend/cypress/e2e(trackerFlow.cy.ts,errorHandling.cy.ts). Runnpm run test:e2e(headless) ornpm run test:e2e:open. - Mocking/fixtures: rely on RTL queries for DOM; Cypress uses Vite dev server config from
cypress.config.cjs.
Prereq: Node 18+.
cd backend && npm install- Configure environment:
FIREBASE_STORAGE_BUCKETFIREBASE_SERVICE_ACCOUNT_JSONorFIREBASE_PROJECT_ID+FIREBASE_CLIENT_EMAIL+FIREBASE_PRIVATE_KEY(use\nfor newlines) orGOOGLE_APPLICATION_CREDENTIALSANTHROPIC_API_KEYfor report generationPORT(optional, default4000)
npm startto launch the API.
Endpoints:
POST /api/upload-csv– expects CSV body +x-session-id; uploads to Storage and records metadata in Firestore (and user-scoped copy when authenticated).POST /api/submit-survey– stores survey payloads undersessions/{sessionId}/surveysorusers/{uid}/surveys.POST /api/generate-report– proxies prompts to Anthropic Claude and returns the generated report.
ml_inference_function/: deployable Python HTTP function for performance scoring; set its URL inVITE_PREDICTION_ENDPOINT.cloudrun/: Cloud Run CSV ingestor wiring Storage events to Firestore/BigQuery (seecloudrun/README.md).analysis/: local data prep and model training assets.tracker-app/: legacy CRA UI; kept for context, not wired into the current Vite app.
- Landing → user chooses Sign up / Sign in / Explore: language toggle persists choice.
- Auth (
/auth): email/password, Google, or anonymous login. On success,TrackingSessionProvidermarks anonymous vs. identified sessions and redirects to/dashboard. - Onboarding survey/consent (
/onboarding/...): required unless anonymous; data saved to Firestore viasaveSurveyAndConsentand used to gate protected routes. - Calibration (
/calibration): webcam permission + WebGazer session; validation enforcesRECALIBRATION_THRESHOLD; exiting stops tracking, continuing routes to training. - Training (
/training): collects gaze/mouse/target telemetry for the session. - Results (
/results): computes analytics, exports CSV locally, optional upload to backend/Storage withx-session-id, and saves session + calibration + survey metadata to Firestore (and leaderboard if opted-in). - Report (
/report): generates AI coaching report via backend Anthropic proxy; predicted score fetched from ML endpoint or fallback heuristic. - History/Leaderboard (
/sessions,/leaderboard): renders stored sessions and optional leaderboard entries; hydration occurs after auth.
- Auth: email/Google/anonymous flows land on
/dashboardand respect persisted language settings. - Onboarding: survey + consent gates block tracker pages until completed; state survives reload via localStorage/Firestore hydration.
- Calibration: webcam permission gating, validation respects
RECALIBRATION_THRESHOLD, and exiting stops WebGazer; proceeding routes into training. - Training → Results: telemetry is captured, analytics render (reaction times, gaze/mouse accuracy, sync), and CSV export/upload succeeds with
x-session-idmetadata stored in Firestore/Storage. - Reports + predictions:
ReportPagesurfaces Anthropic errors when the API key is missing, and score prediction falls back gracefully when the ML endpoint is absent. - Leaderboard/history: sessions and leaderboard entries write to Firestore and re-hydrate on dashboard/leaderboard/sessions pages; consent and calibration status persist across tabs.
- Localization: ko/en toggle persists and updates UI copy across landing, dashboard, tracker, and report flows.