# GamerComp.com - AI Game Arcade Mobile-first game arcade where kids (8-16) play AI-generated HTML5 canvas games, create games via wizard, and earn XP. ## Quick Reference ```bash ./deploy.sh # Build + restart + reload nginx ./deploy.sh --clear-cloudflare # Also purge CDN cache pm2 logs gamercomp-api --lines 50 sudo -u postgres psql -d game_arcade ``` ## Tech Stack | Layer | Tech | |-------|------| | Frontend | React 18, Vite, React Router, PWA | | Backend | Node.js, Express, PostgreSQL, Redis | | Auth | JWT + FingerprintJS (guests) | | AI (generation) | Claude Sonnet (`claude-sonnet-4-20250514`) — streaming | | AI (lightweight) | Claude Haiku (`claude-haiku-4-5-20251001`) — tweaks, refinement, summaries | | Push | Web Push (VAPID) via `web-push` | | Infra | DigitalOcean, Nginx, PM2, Cloudflare | ## Project Structure ``` frontend/src/ ├── pages/ │ ├── Play.jsx # Game player + DevToolbar (P key) │ ├── CreateWizard.jsx # 3-step wizard + SSE progress │ ├── Dashboard.jsx # "My Games" - collections + created games only │ ├── Profile.jsx # Stats, streaks, XP activity, achievements, history │ ├── Arcade.jsx # Game browser with live previews │ └── ... ├── components/ │ ├── Header.jsx # Sticky nav (static on /play/*), mobile menu │ ├── DevToolbar.jsx # Tweak, refine, code editor (P key) │ ├── TweakPanel.jsx # 3-step: preview → confirm → success │ ├── GameCard.jsx # Live preview with audio mock │ ├── OnboardingTutorial.jsx # First-time wizard (DB-persisted) │ └── ... ├── context/AuthContext.jsx └── api.js # 180s timeout, SSE streaming, push backend/src/ ├── routes/ │ ├── creation.js # Background generation + SSE streaming │ ├── localai.js # Haiku tweaks: preview, classify, apply, review │ ├── push.js # VAPID key, subscribe/unsubscribe │ └── ... └── utils/ ├── claude.js # Sonnet: generateGameStream, regenerateGameStream ├── haiku.js # preprocessTweak, explainError, summarize* ├── localAI.js # refinePrompt, classifyTweak, applyTweak └── pushNotify.js # Web push send/subscribe ``` ## AI Architecture **Haiku-first**: All lightweight AI uses Claude Haiku directly. | Task | Model | Location | |------|-------|----------| | Game generation/refinement | Sonnet (streaming) | `claude.js` | | Tweak preview/apply | Haiku | `localAI.js` | | Prompt refinement | Haiku | `localAI.js` | | Code review | Haiku | `localai.js` route | | Error explanation | Haiku | `haiku.js` | | Summaries | Haiku | `haiku.js` | ## Background Generation + SSE 1. `POST /api/creation/:id/generate` returns immediately 2. Backend runs async, streams progress to `activeGenerations` Map (5min TTL) 3. Client connects `GET /api/creation/:id/stream?token=JWT` 4. SSE replays buffered events, streams new ones 5. On complete: DB save, in-app notification, email, push **SSE auth**: JWT via `?token=` query param. **Nginx**: Requires `proxy_buffering off` for `/api`. ## Key Pages ### Dashboard → "My Games" - Collections grid (4 max shown) - Created games list with status badges - Create button — no stats/XP (moved to Profile) ### Profile (own) - Avatar, XP bar, level icon - Quick stats: Games Created, Played, Time, Total XP - Streaks: Login (🔥), Creation (⚡) with milestones - XP activity: Recent transactions - Achievements grid (earned/locked toggle) - Tabs: Created Games, Favorites, Play History ### Play + DevToolbar - Press **P** to open (creators only, draft/testing) - **Tweak tab**: 3-step flow with Haiku preview → confirm → success - **Edit tab**: Code editor with Haiku review before save - **Refine tab**: Full Sonnet regeneration with SSE progress - **Prompt tab**: View generation prompt - Test 30s minimum before publishing ### Header - Sticky on all pages except `/play/*` (static there) - Mobile hamburger menu - Token display, notification bell, avatar+level badge ### Onboarding - 4-step welcome wizard for new users - Persisted in DB (`onboarding_complete` column) - Survives cache clear/reload ## API Endpoints ``` # Public GET /api/arcade/games|:id GET /api/leaderboard/players|creators|games GET /api/push/vapid-key # Auth POST /api/auth/register|login|guest-login POST /api/auth/forgot-password|reset-password # Authenticated POST /api/play/start|finish|rate|favorite POST /api/creation/start|:id/generate|refine|publish GET /api/creation/:id/stream # SSE (?token=JWT) POST /api/localai/refine-prompt|classify|tweak/:gameId POST /api/localai/tweak/:gameId/preview # Haiku preview POST /api/localai/review-code/:gameId # Haiku code review POST /api/localai/save-code/:gameId # Save manual edits POST /api/push/subscribe|unsubscribe GET /api/users/me ``` ## Database Tables **Core**: users, games, plays, ratings, high_scores **Social**: favorites, follows, notifications, collections **Progress**: achievements, user_achievements, xp_transactions **Education**: classrooms, classroom_students, assignments **Push**: push_subscriptions **Reports**: game_reports, bug_reports ## Common Tasks ```bash # Add page 1. frontend/src/pages/NewPage.jsx 2. Add route in App.jsx 3. Add to Header.jsx if needed 4. ./deploy.sh # Add API endpoint 1. backend/src/routes/file.js 2. frontend/src/api.js method 3. Mount in app.js if new file 4. pm2 restart gamercomp-api # Database change sudo -u postgres psql -d game_arcade GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO gamearc; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO gamearc; ``` ## Troubleshooting | Issue | Fix | |-------|-----| | UI not updating | `/clear-cache.html` or Ctrl+Shift+R | | PM2 errors | `pm2 flush && pm2 restart gamercomp-api` | | SSE not working | Check nginx `proxy_buffering off` | | Generation timeout | Check 180s timeouts (nginx, api.js) | | Iframe blank | Needs `sandbox="allow-scripts"` | | Push not delivered | Check VAPID keys, subscriptions pruned on 410 | | Mobile keyboard hiding | Use `font-size: 16px` on inputs | ## Architecture Notes **Iframe Communication**: Games export `pauseGame()`, `resumeGame()`, `pauseMusic()`, `resumeMusic()`, `gameScore`, `setMusicEnabled()`, `setSfxEnabled()` on window. **Content Safety**: Multi-layer filtering (profanity, PII, violence). Gaming allowlist. Kid-friendly errors. **Audio Mocking**: GameCard.jsx mocks `AudioContext` and `Audio` completely to prevent sounds in previews. **Mobile Touch**: Play.jsx uses `onTouchEnd` with `e.preventDefault()` for buttons. Textareas need `font-size: 16px` to prevent iOS zoom and keyboard issues.