Monorepo MVP for ChessTrainer (SPA web + API + worker + shared contracts).
Production web: https://yourchesstrainer.vercel.app
- Node.js 20+
- npm 10+
apps/web: React + Vite SPA (desktop-first)apps/api: NestJS REST APIapps/worker: async worker runtime skeletonpackages/shared-contracts: shared contract/schema package
npm install
cp .env.example .env
npm run dev- Configure Supabase keys in
.env:SUPABASE_URLSUPABASE_JWT_AUDIENCESUPABASE_SERVICE_ROLE_KEY(required for API-side account deletion)VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
- Configure API persistence + CORS:
DATABASE_URLWEB_APP_ORIGIN
- Open web app on
/registerto create account with age-gate checkbox (16+). - Login is available on
/login. - Successful login/signup with active session redirects to
/onboarding. - Logout button in onboarding invalidates the session and redirects to
/login. - On first authenticated session, web calls
GET /auth/meto upsert localusersidentity by Supabasesub. - Account deletion is available in onboarding after explicit confirmation and calls
POST /auth/delete-account. - Security baseline (Story 1.6):
- API enforces HTTPS-only in
production. x-trace-idis attached to responses and reused in audit logs.GET /auth/audit-logsis available for authenticated audit-log review.
- API enforces HTTPS-only in
- Chess.com candidate listing (Story 2.1):
- Onboarding includes username fetch to list recent candidate games as selectable entries.
- API endpoint:
GET /imports/chess-com/candidate-games?username=<name>&archives_count=<n>. - Unavailable archive periods are returned and displayed gracefully.
- Selected import (Story 2.2):
- API endpoint:
POST /imports/chess-com/import-selected. - Only selected game URLs are persisted for the authenticated user.
- Import summary returns
imported_count,already_existing_count, andfailed_count.
- API endpoint:
- Incremental re-import without duplicates (Story 2.3):
- API endpoint:
POST /imports/chess-com/reimport. - Scans recent archives and inserts only new games for the authenticated user.
- Dedup is deterministic using
(userId, gameUrl); existing rows are skipped. - Summary returns
scanned_count,imported_count,already_existing_count, andfailed_count.
- API endpoint:
- Chess.com retry/backoff resilience (Story 2.4):
- Transient Chess.com failures (
408,429,5xx, network errors) are retried with exponential backoff. - Retry budget and delays are configurable via:
CHESSCOM_RETRY_MAX_RETRIESCHESSCOM_RETRY_BASE_DELAY_MSCHESSCOM_RETRY_MAX_DELAY_MS
- Final failure status is explicit in API responses (archive listing errors include HTTP status and attempts; per-period failures include reason suffix
_after_<n>_attempts).
- Transient Chess.com failures (
- Analysis job enqueue (Story 3.1):
- API endpoint:
POST /analysis/jobs. - Enqueues asynchronous analysis jobs for imported games of the authenticated user.
- Returns
enqueued_count,skipped_count, and per-job tracking metadata (job_id,queue_job_id, initialstatus). - Jobs with existing active status (
queued/running) are skipped to avoid duplicate active processing.
- API endpoint:
- Worker Stockfish execution (Story 3.2):
- Worker scans
analysis_jobswithstatus=queued, locks them torunning, then analyzes game PGN moves. - Each ply stores one persisted evaluation row (
analysis_move_evaluations) with played move vs Stockfish best move and score. - Timeout and retry policy are configurable:
ANALYSIS_TIMEOUT_MS(default60000)ANALYSIS_RETRY_MAX_RETRIES(default2)ANALYSIS_RETRY_BASE_DELAY_MS(default500)ANALYSIS_RETRY_MAX_DELAY_MS(default5000)
- Stockfish binary path and worker polling:
STOCKFISH_BIN_PATH(defaultstockfish)WORKER_POLL_INTERVAL_MS,WORKER_BATCH_SIZE,WORKER_RUN_ONCE
- Worker scans
- Critical mistake extraction + summaries (Story 3.3):
- Worker extracts
critical_mistakeswhen evaluation drop is>= 200cp(>= 2.0pawns), with severity and phase categories. - Mistakes are persisted per analyzed game and deduplicated per
(analysis_job_id, ply_index). - User aggregates are regenerated from recent completed jobs into
user_mistake_summaries.
- Worker extracts
- Analysis status polling with progress + ETA (Story 3.4):
- API endpoint:
GET /analysis/jobs/:job_id. - Returns explicit per-job execution state (
queued/running/completed/failed) withprogress_percentandeta_seconds. - Onboarding polls tracked jobs every 2s, shows a visible progress bar + ETA, and displays explicit completion state when all tracked jobs are terminal.
- API endpoint:
- API contract + observability enforcement (Story 3.5):
- Added contract tests to enforce
snake_casepublic payload keys (apps/api/src/contracts/api-snake-case.contract.spec.ts). - API emits structured JSON logs for completed requests with
trace_id, status, duration, and user context when available. - API captures controller/runtime exceptions through Sentry when
SENTRY_DSNis configured. - Worker emits structured JSON logs for bootstrap/batch/job events and captures failures through Sentry (
SENTRY_DSNorWORKER_SENTRY_DSN). - Web initializes optional Sentry capture with environment/release metadata (
VITE_SENTRY_*) and captures global runtime errors.
- Added contract tests to enforce
- Mistake position as playable puzzle (Story 4.1):
- API endpoint:
GET /puzzles/next(authenticated). - Returns the latest critical mistake as a puzzle payload (
fen,side_to_move,objective, contextual metadata). - New protected web route:
/puzzle. - Puzzle page fetches and renders the position on an interactive board, plus objective/context panel.
- If no analyzed mistake exists yet, the page displays an explicit empty state.
- API endpoint:
- Attempt evaluation + retry loop (Story 4.2):
- API endpoint:
POST /puzzles/:puzzle_id/attemptwithattempted_move_uci. - Server evaluates move vs stored
best_move_uciand returns explicit feedback payload (is_correct,status,feedback_*,retry_available). - Puzzle page evaluates the played move immediately and shows success/failure feedback.
- On failure, user can retry the same position with a one-click board reset.
- API endpoint:
- Puzzle session sequencing (Story 4.3):
- API endpoint:
GET /puzzles/session?limit=<n>to fetch a sequence of mistake-based puzzles. - Puzzle page now runs a session flow (up to 10 puzzles), with explicit progress at the top.
- Users can continue after solving a puzzle or skip the current puzzle.
- Session progress updates as users advance (
completed / total, solved count, skipped count).
- API endpoint:
- Move explanations (Story 4.4):
- Attempt evaluation now returns two explanation fields:
wrong_move_explanationbest_move_explanation
- Web renders the dedicated
ExplanationPanelafter each evaluated attempt. - Panel explains both sides of the correction:
- why the played move is weaker
- why the best move is stronger
- Includes a short “À retenir” takeaway for fast daily review.
- Attempt evaluation now returns two explanation fields:
- Accessibility hardening for puzzle flow (Story 4.5):
- Puzzle flow now exposes clearer keyboard support (board helper text + keyboard-operable squares).
- Focus states are persistent and highly visible across interactive controls (
:focus-visiblestyling). - Puzzle attempt feedback announces status changes and receives programmatic focus after evaluation.
- Board square labels now include piece names (screen-reader friendly), not only unicode symbols.
- Core interactive controls respect minimum
44x44target sizing guidance.
- Session progress summary (Story 5.1):
- API endpoints:
GET /progress/summary(key metrics + recent mistakes)POST /progress/sessions(persist one completed puzzle session)
- Puzzle page now persists a session summary automatically once a session is completed.
- New protected web route:
/progress. - Progress page shows compact metrics:
- sessions completed
- puzzles completed / solved / skipped
- success indicator (%)
- recurring mistake categories
- Data model update: new
puzzle_sessionstable (PuzzleSessionPrisma model).
- API endpoints:
- Recurring mistake trends (Story 5.2):
- API endpoint:
GET /progress/trends?days=<n>&limit=<n>. - Trends rank recurring mistake categories by recent count.
- Each category includes a clear direction signal (
up,down,stable,new) by comparing recent vs previous window. - New protected web route:
/progress/trends. - Trends view shows ranked categories with direction badges and recent-vs-previous delta.
- API endpoint:
- Stored data inventory (Story 5.3):
- API endpoint:
GET /data/inventory. - Returns stored-data counts for account transparency:
- games
- analyses
- move evaluations
- critical mistakes
- puzzle sessions
- Returns latest update context with timestamps (last imported game, last analysis update, last detected critical mistake).
- New protected web route:
/data/inventory. - Inventory page displays counts and recent data context for transparent storage visibility.
- API endpoint:
- Dataset deletion controls (Story 5.4):
- API endpoint:
POST /data/delete-datasets. - Supports selected dataset deletion:
gamesanalysespuzzle_sessions
- Returns deletion summary with
deleted_counts+remaining_counts. - Data inventory page now includes explicit selection + confirmation before deletion.
- After deletion, inventory refreshes immediately and progress views reflect updated backend state on next load.
- API endpoint:
- Coach student context access (Story 6.1):
- Prisma model
CoachStudentAccessdefines explicit authorized coach→student links. - API endpoints:
GET /coach/studentsPOST /coach/context/select
- Coach-only access is enforced server-side (
role=coachrequired). - Unauthorized student context selection is blocked (
403). - New protected web route:
/coach/contextto list authorized students and activate one context. - Selected context metadata is persisted client-side for next coach stories.
- Prisma model
- Coach import + mistake review (Story 6.2):
- API endpoints:
POST /coach/review/importGET /coach/review/mistakes?student_user_id=<id>&limit=<n>
- Endpoints are coach-only and restricted to authorized
coach_student_accessesscope. - New protected web route:
/coach/review. - Coach review flow supports:
- importing a selected student’s recent games from Chess.com
- listing key mistakes with explanations
- opening each mistake with board context + rationale panel
- Coach context page now links directly to the review workspace once a student context is selected.
- API endpoints:
npm run lintnpm run typechecknpm run testnpm run buildnpm run security:checknpm run perf:webnpm run ci
This story initializes app skeletons only. Redis/Postgres and feature modules arrive in next stories.